diff --git a/libs/ardour/analyser.cc b/libs/ardour/analyser.cc index b5a9d08e81..07d0e77d55 100644 --- a/libs/ardour/analyser.cc +++ b/libs/ardour/analyser.cc @@ -103,7 +103,7 @@ Analyser::work () boost::shared_ptr afs = boost::dynamic_pointer_cast (src); - if (afs && afs->length(afs->natural_position())) { + if (afs && !afs->empty()) { Glib::Threads::Mutex::Lock lm (analysis_active_lock); analyse_audio_file_source (afs); } diff --git a/libs/ardour/analysis_graph.cc b/libs/ardour/analysis_graph.cc index 4e0b5f01f8..827584b3dc 100644 --- a/libs/ardour/analysis_graph.cc +++ b/libs/ardour/analysis_graph.cc @@ -76,23 +76,24 @@ AnalysisGraph::analyze_region (AudioRegion const* region, bool raw, ARDOUR::Prog _session->nominal_sample_rate(), n_channels, n_samples, - region->length())); - + region->length_samples())); interleaver->add_output(chunker); chunker->add_output (analyser); samplecnt_t x = 0; - samplecnt_t length = region->length(); + samplecnt_t length = region->length_samples(); while (x < length) { samplecnt_t chunk = std::min (_max_chunksize, length - x); samplecnt_t n = 0; for (unsigned int channel = 0; channel < region->n_channels(); ++channel) { memset (_buf, 0, chunk * sizeof (Sample)); + if (raw) { - n = region->read_raw_internal (_buf, region->start() + x, chunk, channel); + n = region->read_raw_internal (_buf, region->start_sample() + x, chunk, channel); } else { - n = region->read_at (_buf, _mixbuf, _gainbuf, region->position() + x, chunk, channel); + n = region->read_at (_buf, _mixbuf, _gainbuf, region->position_sample() + x, chunk, channel); } + ConstProcessContext context (_buf, n, 1); if (n < _max_chunksize) { context().set_flag (ProcessContext::EndOfInput); @@ -121,7 +122,7 @@ AnalysisGraph::analyze_region (AudioRegion const* region, bool raw, ARDOUR::Prog } void -AnalysisGraph::analyze_range (boost::shared_ptr route, boost::shared_ptr pl, const std::list& range) +AnalysisGraph::analyze_range (boost::shared_ptr route, boost::shared_ptr pl, const std::list& range) { const uint32_t n_audio = route->n_inputs().n_audio(); if (n_audio == 0 || n_audio > _max_chunksize) { @@ -129,7 +130,7 @@ AnalysisGraph::analyze_range (boost::shared_ptr route, boost::shared_ptr< } const samplecnt_t n_samples = _max_chunksize - (_max_chunksize % n_audio); - for (std::list::const_iterator j = range.begin(); j != range.end(); ++j) { + for (std::list::const_iterator j = range.begin(); j != range.end(); ++j) { interleaver.reset (new Interleaver ()); interleaver->init (n_audio, _max_chunksize); @@ -137,17 +138,21 @@ AnalysisGraph::analyze_range (boost::shared_ptr route, boost::shared_ptr< chunker.reset (new Chunker (n_samples)); analyser.reset (new Analyser ( _session->nominal_sample_rate(), - n_audio, n_samples, (*j).length())); + n_audio, n_samples, (*j).length_samples())); interleaver->add_output(chunker); chunker->add_output (analyser); samplecnt_t x = 0; - while (x < j->length()) { - samplecnt_t chunk = std::min (_max_chunksize, (*j).length() - x); + const samplecnt_t rlen = j->length().samples(); + const samplepos_t rpos = j->start().samples(); + + while (x < rlen) { + samplecnt_t chunk = std::min (_max_chunksize, rlen - x); samplecnt_t n = 0; + for (uint32_t channel = 0; channel < n_audio; ++channel) { - n = pl->read (_buf, _mixbuf, _gainbuf, (*j).start + x, chunk, channel); + n = pl->read (_buf, _mixbuf, _gainbuf, timepos_t (rpos + x), timecnt_t (chunk), channel).samples(); ConstProcessContext context (_buf, n, 1); if (n < _max_chunksize) { @@ -165,11 +170,11 @@ AnalysisGraph::analyze_range (boost::shared_ptr route, boost::shared_ptr< std::string name = string_compose (_("%1 (%2..%3)"), route->name(), Timecode::timecode_format_sampletime ( - (*j).start, + rpos, _session->nominal_sample_rate(), 100, false), Timecode::timecode_format_sampletime ( - (*j).start + (*j).length(), + (*j).end().samples(), _session->nominal_sample_rate(), 100, false) ); diff --git a/libs/ardour/ardour/analysis_graph.h b/libs/ardour/ardour/analysis_graph.h index 3651763fff..cac6e45b70 100644 --- a/libs/ardour/ardour/analysis_graph.h +++ b/libs/ardour/ardour/analysis_graph.h @@ -48,7 +48,8 @@ class LIBARDOUR_API AnalysisGraph { void analyze_region (ARDOUR::AudioRegion const*, bool raw = false, ARDOUR::Progress* = 0); void analyze_region (boost::shared_ptr, bool raw = false); - void analyze_range (boost::shared_ptr, boost::shared_ptr, const std::list&); + void analyze_range (boost::shared_ptr, boost::shared_ptr, const std::list&); + const AnalysisResults& results () const { return _results; } void cancel () { _canceled = true; } diff --git a/libs/ardour/ardour/audio_playlist_source.h b/libs/ardour/ardour/audio_playlist_source.h index 0842653d20..067ed4e154 100644 --- a/libs/ardour/ardour/audio_playlist_source.h +++ b/libs/ardour/ardour/audio_playlist_source.h @@ -51,13 +51,13 @@ public: int set_state (const XMLNode&, int version); bool can_truncate_peaks() const { return false; } - bool can_be_analysed() const { return _length > 0; } + bool can_be_analysed() const { return _length.positive(); } protected: friend class SourceFactory; AudioPlaylistSource (Session&, const PBD::ID& orig, const std::string& name, boost::shared_ptr, uint32_t chn, - sampleoffset_t begin, samplecnt_t len, Source::Flag flags); + timepos_t const & begin, timepos_t const & len, Source::Flag flags); AudioPlaylistSource (Session&, const XMLNode&); diff --git a/libs/ardour/ardour/audioanalyser.h b/libs/ardour/ardour/audioanalyser.h index 140b567977..8755082d75 100644 --- a/libs/ardour/ardour/audioanalyser.h +++ b/libs/ardour/ardour/audioanalyser.h @@ -30,7 +30,7 @@ namespace ARDOUR { -class Readable; +class AudioReadable; class Session; class LIBARDOUR_API AudioAnalyser : public boost::noncopyable { @@ -44,7 +44,7 @@ class LIBARDOUR_API AudioAnalyser : public boost::noncopyable { /* analysis object should provide a run method that accepts a path to write the results to (optionally empty) - a Readable* to read data from + a AudioReadable* to read data from and a reference to a type-specific container to return the results. */ @@ -60,7 +60,7 @@ class LIBARDOUR_API AudioAnalyser : public boost::noncopyable { samplecnt_t stepsize; int initialize_plugin (AnalysisPluginKey name, float sample_rate); - int analyse (const std::string& path, Readable*, uint32_t channel); + int analyse (const std::string& path, AudioReadable*, uint32_t channel); /* instances of an analysis object will have this method called whenever there are results to process. if out is non-null, diff --git a/libs/ardour/ardour/audiofilesource.h b/libs/ardour/ardour/audiofilesource.h index df0bb96755..c7293b9567 100644 --- a/libs/ardour/ardour/audiofilesource.h +++ b/libs/ardour/ardour/audiofilesource.h @@ -70,7 +70,7 @@ public: int set_state (const XMLNode&, int version); bool can_truncate_peaks() const { return true; } - bool can_be_analysed() const { return _length > 0; } + bool can_be_analysed() const { return _length.positive(); } static bool safe_audio_file_extension (const std::string& path); diff --git a/libs/ardour/ardour/audioplaylist.h b/libs/ardour/ardour/audioplaylist.h index 2311bd0e19..1eb277d6de 100644 --- a/libs/ardour/ardour/audioplaylist.h +++ b/libs/ardour/ardour/audioplaylist.h @@ -41,9 +41,9 @@ public: AudioPlaylist (Session&, const XMLNode&, bool hidden = false); AudioPlaylist (Session&, std::string name, bool hidden = false); AudioPlaylist (boost::shared_ptr, std::string name, bool hidden = false); - AudioPlaylist (boost::shared_ptr, samplepos_t start, samplecnt_t cnt, std::string name, bool hidden = false); + AudioPlaylist (boost::shared_ptr, timepos_t const & start, timepos_t const & cnt, std::string name, bool hidden = false); - samplecnt_t read (Sample *dst, Sample *mixdown, float *gain_buffer, samplepos_t start, samplecnt_t cnt, uint32_t chan_n=0); + timecnt_t read (Sample *dst, Sample *mixdown, float *gain_buffer, timepos_t const & start, timecnt_t const & cnt, uint32_t chan_n=0); bool destroy_region (boost::shared_ptr); diff --git a/libs/ardour/ardour/audioregion.h b/libs/ardour/ardour/audioregion.h index 57e042521b..97a4db9c1b 100644 --- a/libs/ardour/ardour/audioregion.h +++ b/libs/ardour/ardour/audioregion.h @@ -62,7 +62,7 @@ class Filter; class AudioSource; -class LIBARDOUR_API AudioRegion : public Region +class LIBARDOUR_API AudioRegion : public Region, public AudioReadable { public: static void make_property_quarks (); @@ -104,26 +104,28 @@ class LIBARDOUR_API AudioRegion : public Region boost::shared_ptr inverse_fade_out() { return _inverse_fade_out.val (); } boost::shared_ptr envelope() { return _envelope.val (); } - Evoral::Range body_range () const; + Temporal::Range body_range () const; virtual samplecnt_t read_peaks (PeakData *buf, samplecnt_t npeaks, samplecnt_t offset, samplecnt_t cnt, uint32_t chan_n=0, double samples_per_pixel = 1.0) const; - /* Readable interface */ + /* AudioReadable interface */ - virtual samplecnt_t read (Sample*, samplepos_t pos, samplecnt_t cnt, int channel) const; + samplecnt_t read (Sample*, samplepos_t pos, samplecnt_t cnt, int channel) const; + samplecnt_t readable_length_samples() const { return length_samples(); } + uint32_t n_channels() const { return _sources.size(); } - virtual samplecnt_t read_at (Sample *buf, Sample *mixdown_buf, float *gain_buf, + samplecnt_t read_at (Sample *buf, Sample *mixdown_buf, float *gain_buf, samplepos_t position, samplecnt_t cnt, uint32_t chan_n = 0) const; - virtual samplecnt_t master_read_at (Sample *buf, Sample *mixdown_buf, float *gain_buf, + samplecnt_t master_read_at (Sample *buf, Sample *mixdown_buf, float *gain_buf, samplepos_t position, samplecnt_t cnt, uint32_t chan_n=0) const; - virtual samplecnt_t read_raw_internal (Sample*, samplepos_t, samplecnt_t, int channel) const; + samplecnt_t read_raw_internal (Sample*, samplepos_t, samplecnt_t, int channel) const; XMLNode& state (); XMLNode& get_basic_state (); @@ -245,7 +247,7 @@ class LIBARDOUR_API AudioRegion : public Region protected: /* default constructor for derived (compound) types */ - AudioRegion (Session& s, samplepos_t, samplecnt_t, std::string name); + AudioRegion (Session& s, timecnt_t const &, timecnt_t const &, std::string name); int _set_state (const XMLNode&, int version, PBD::PropertyChange& what_changed, bool send_signal); }; diff --git a/libs/ardour/ardour/audiorom.h b/libs/ardour/ardour/audiorom.h index eda1e117b1..870487c7bd 100644 --- a/libs/ardour/ardour/audiorom.h +++ b/libs/ardour/ardour/audiorom.h @@ -27,7 +27,7 @@ namespace ARDOUR { class Session; -class LIBARDOUR_API AudioRom : public Readable +class LIBARDOUR_API AudioRom : public AudioReadable { public: static boost::shared_ptr new_rom (Sample*, size_t); diff --git a/libs/ardour/ardour/audiosource.h b/libs/ardour/ardour/audiosource.h index 632b34636a..2cd7aa05d6 100644 --- a/libs/ardour/ardour/audiosource.h +++ b/libs/ardour/ardour/audiosource.h @@ -41,20 +41,17 @@ namespace ARDOUR { -class LIBARDOUR_API AudioSource : virtual public Source, - public ARDOUR::Readable +class LIBARDOUR_API AudioSource : virtual public Source, public ARDOUR::AudioReadable { public: AudioSource (Session&, const std::string& name); AudioSource (Session&, const XMLNode&); virtual ~AudioSource (); - samplecnt_t readable_length() const { return _length; } + samplecnt_t readable_length_samples() const { return _length.samples(); } virtual uint32_t n_channels() const { return 1; } - virtual bool empty() const; - samplecnt_t length (samplepos_t pos) const; - void update_length (samplecnt_t cnt); + void update_length (timecnt_t const & cnt); virtual samplecnt_t available_peaks (double zoom) const; @@ -107,7 +104,19 @@ class LIBARDOUR_API AudioSource : virtual public Source, static bool _build_missing_peakfiles; static bool _build_peakfiles; - samplecnt_t _length; + /* these collections of working buffers for supporting + playlist's reading from potentially nested/recursive + sources assume SINGLE THREADED reads by the butler + thread, or a lock around calls that use them. + */ + + static std::vector > _mixdown_buffers; + static std::vector > _gain_buffers; + static Glib::Threads::Mutex _level_buffer_lock; + + static void ensure_buffers_for_level (uint32_t, samplecnt_t); + static void ensure_buffers_for_level_locked (uint32_t, samplecnt_t); + std::string _peakpath; int initialize_peakfile (const std::string& path, const bool in_session = false); diff --git a/libs/ardour/ardour/auditioner.h b/libs/ardour/ardour/auditioner.h index 54d8d08801..28be1094f0 100644 --- a/libs/ardour/ardour/auditioner.h +++ b/libs/ardour/ardour/auditioner.h @@ -102,7 +102,7 @@ private: samplepos_t current_sample; mutable GATOMIC_QUAL gint _auditioning; Glib::Threads::Mutex lock; - samplecnt_t length; + timecnt_t length; sampleoffset_t _seek_sample; bool _seeking; bool _seek_complete; @@ -120,7 +120,7 @@ private: static void*_drop_ports (void*); void actually_drop_ports (); void output_changed (IOChange, void*); - sampleoffset_t _import_position; + timepos_t _import_position; }; }; /* namespace ARDOUR */ diff --git a/libs/ardour/ardour/automatable.h b/libs/ardour/ardour/automatable.h index 2bb81622b2..078ff98283 100644 --- a/libs/ardour/ardour/automatable.h +++ b/libs/ardour/ardour/automatable.h @@ -85,7 +85,7 @@ public: boost::shared_ptr automation_control (const Evoral::Parameter& id) const; virtual void add_control(boost::shared_ptr); - virtual bool find_next_event (double start, double end, Evoral::ControlEvent& ev, bool only_active = true) const; + virtual bool find_next_event (Temporal::timepos_t const & start, Temporal::timepos_t const & end, Evoral::ControlEvent& ev, bool only_active = true) const; void clear_controls (); virtual void non_realtime_locate (samplepos_t now); @@ -131,9 +131,8 @@ protected: SlavableControlList slavables () const { return SlavableControlList(); } -protected: - void find_next_ac_event (boost::shared_ptr, double start, double end, Evoral::ControlEvent& ev) const; - void find_prev_ac_event (boost::shared_ptr, double start, double end, Evoral::ControlEvent& ev) const; + void find_next_ac_event (boost::shared_ptr, Temporal::timepos_t const & start, Temporal::timepos_t const & end, Evoral::ControlEvent& ev) const; + void find_prev_ac_event (boost::shared_ptr, Temporal::timepos_t const & start, Temporal::timepos_t const & end, Evoral::ControlEvent& ev) const; private: PBD::ScopedConnectionList _control_connections; ///< connections to our controls' signals diff --git a/libs/ardour/ardour/automation_control.h b/libs/ardour/ardour/automation_control.h index 3a13d1ce16..7dbfa7aa71 100644 --- a/libs/ardour/ardour/automation_control.h +++ b/libs/ardour/ardour/automation_control.h @@ -85,8 +85,8 @@ public: } void set_automation_state(AutoState as); - void start_touch(double when); - void stop_touch(double when); + void start_touch(timepos_t const & when); + void stop_touch(timepos_t const & when); /* inherited from PBD::Controllable. */ virtual double get_value () const; diff --git a/libs/ardour/ardour/automation_list.h b/libs/ardour/ardour/automation_list.h index 22ac87866f..f272599693 100644 --- a/libs/ardour/ardour/automation_list.h +++ b/libs/ardour/ardour/automation_list.h @@ -73,20 +73,21 @@ private: class LIBARDOUR_API AutomationList : public Evoral::ControlList, public PBD::StatefulDestructible { public: - AutomationList (const Evoral::Parameter& id, const Evoral::ParameterDescriptor& desc); - AutomationList (const Evoral::Parameter& id); + AutomationList (const Evoral::Parameter& id, const Evoral::ParameterDescriptor& desc, Temporal::TimeDomain); + AutomationList (const Evoral::Parameter& id, Temporal::TimeDomain); AutomationList (const XMLNode&, Evoral::Parameter id); AutomationList (const AutomationList&); - AutomationList (const AutomationList&, double start, double end); + AutomationList (const AutomationList&, timepos_t const & start, timepos_t const & end); ~AutomationList(); virtual boost::shared_ptr create(const Evoral::Parameter& id, - const Evoral::ParameterDescriptor& desc); + const Evoral::ParameterDescriptor& desc, + Temporal::TimeDomain); AutomationList& operator= (const AutomationList&); void thaw (); - bool paste (const ControlList&, double, BeatsSamplesConverter const&); + bool paste (const ControlList&, timepos_t const &, BeatsSamplesConverter const&); void set_automation_state (AutoState); AutoState automation_state() const; @@ -103,11 +104,11 @@ public: static PBD::Signal1 AutomationListCreated; - void start_write_pass (double when); - void write_pass_finished (double when, double thinning_factor=0.0); + void start_write_pass (timepos_t const & when); + void write_pass_finished (timepos_t const & when, double thinning_factor=0.0); - void start_touch (double when); - void stop_touch (double when); + void start_touch (timepos_t const & when); + void stop_touch (timepos_t const & when); bool touching () const { return g_atomic_int_get (&_touching) != 0; } bool writing () const { return _state == Write; } diff --git a/libs/ardour/ardour/beats_samples_converter.h b/libs/ardour/ardour/beats_samples_converter.h index 474772c759..cae7ff3ffb 100644 --- a/libs/ardour/ardour/beats_samples_converter.h +++ b/libs/ardour/ardour/beats_samples_converter.h @@ -16,10 +16,10 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include - #include "temporal/beats.h" -#include "evoral/TimeConverter.h" +#include "temporal/superclock.h" +#include "temporal/time_converter.h" +#include "temporal/types.h" #include "ardour/libardour_visibility.h" #include "ardour/types.h" @@ -27,49 +27,31 @@ #ifndef __ardour_beats_samples_converter_h__ #define __ardour_beats_samples_converter_h__ +namespace Temporal { + class TempoMap; +} + namespace ARDOUR { -class TempoMap; - -/** Converter between quarter-note beats and samples. Takes distances in quarter-note beats or samples - * from some origin (supplied to the constructor in samples), and converts - * them to the opposite unit, taking tempo changes into account. +/** Converter between quarter-note beats and samplepos_t. Takes distances in + * quarter-note beats or samplepos_t from some origin (supplied to the + * constructor in samplepos_t), and converts them to the opposite unit, + * taking tempo changes into account. */ -class LIBARDOUR_API BeatsSamplesConverter - : public Evoral::TimeConverter { +class LIBARDOUR_API BeatsSamplesConverter : public Temporal::TimeConverter { public: - BeatsSamplesConverter (const TempoMap& tempo_map, samplepos_t origin) - : Evoral::TimeConverter (origin) - , _tempo_map(tempo_map) + BeatsSamplesConverter (const Temporal::TempoMap& tempo_map, Temporal::samplepos_t origin) + : Temporal::TimeConverter (origin) + , _tempo_map (tempo_map) {} - samplepos_t to (Temporal::Beats beats) const; - Temporal::Beats from (samplepos_t samples) const; + samplecnt_t to (Temporal::Beats beats) const; + Temporal::Beats from (samplecnt_t distance) const; private: - const TempoMap& _tempo_map; + const Temporal::TempoMap& _tempo_map; }; -/** Converter between quarter-note beats and samples. Takes distances in quarter-note beats or samples - * from some origin (supplied to the constructor in samples), and converts - * them to the opposite unit, taking tempo changes into account. - */ -class LIBARDOUR_API DoubleBeatsSamplesConverter - : public Evoral::TimeConverter { -public: - DoubleBeatsSamplesConverter (const TempoMap& tempo_map, samplepos_t origin) - : Evoral::TimeConverter (origin) - , _tempo_map(tempo_map) - {} - - samplepos_t to (double beats) const; - double from (samplepos_t samples) const; - -private: - const TempoMap& _tempo_map; -}; - - } /* namespace ARDOUR */ #endif /* __ardour_beats_samples_converter_h__ */ diff --git a/libs/ardour/ardour/convolver.h b/libs/ardour/ardour/convolver.h index 7a335f8287..053dfd6177 100644 --- a/libs/ardour/ardour/convolver.h +++ b/libs/ardour/ardour/convolver.h @@ -39,7 +39,7 @@ public: bool add_impdata ( uint32_t c_in, uint32_t c_out, - boost::shared_ptr r, + boost::shared_ptr r, float gain = 1.0, uint32_t pre_delay = 0, sampleoffset_t offset = 0, @@ -64,10 +64,10 @@ protected: bool _threaded; private: - class ImpData : public Readable + class ImpData : public AudioReadable { public: - ImpData (uint32_t ci, uint32_t co, boost::shared_ptr r, float g, float d, sampleoffset_t s = 0, samplecnt_t l = 0, uint32_t c = 0) + ImpData (uint32_t ci, uint32_t co, boost::shared_ptr r, float g, float d, sampleoffset_t s = 0, samplecnt_t l = 0, uint32_t c = 0) : c_in (ci) , c_out (co) , gain (g) @@ -87,8 +87,8 @@ private: return _readable->read (s, pos + _offset, cnt, _channel); } - samplecnt_t readable_length () const { - samplecnt_t rl = _readable->readable_length (); + samplecnt_t readable_length_samples () const { + samplecnt_t rl = _readable->readable_length_samples (); if (rl < _offset) { return 0; } else if (_length > 0) { @@ -103,7 +103,7 @@ private: } private: - boost::shared_ptr _readable; + boost::shared_ptr _readable; sampleoffset_t _offset; samplecnt_t _length; @@ -172,7 +172,7 @@ public: void run_stereo_no_latency (float* L, float* R, uint32_t); private: - std::vector > _readables; + std::vector > _readables; IRChannelConfig _irc; IRSettings _ir_settings; diff --git a/libs/ardour/ardour/disk_io.h b/libs/ardour/ardour/disk_io.h index 05131321a5..ce933718fb 100644 --- a/libs/ardour/ardour/disk_io.h +++ b/libs/ardour/ardour/disk_io.h @@ -181,13 +181,13 @@ protected: virtual void playlist_changed (const PBD::PropertyChange&) {} virtual void playlist_deleted (boost::weak_ptr); - virtual void playlist_ranges_moved (std::list< Evoral::RangeMove > const &, bool) {} + virtual void playlist_ranges_moved (std::list const &, bool) {} /* The MIDI stuff */ MidiRingBuffer* _midi_buf; - static void get_location_times (const Location* location, samplepos_t* start, samplepos_t* end, samplepos_t* length); + static void get_location_times (const Location* location, timepos_t* start, timepos_t* end, timecnt_t* length); }; } // namespace ARDOUR diff --git a/libs/ardour/ardour/disk_reader.h b/libs/ardour/ardour/disk_reader.h index ccfb9b902f..dca916d791 100644 --- a/libs/ardour/ardour/disk_reader.h +++ b/libs/ardour/ardour/disk_reader.h @@ -73,7 +73,7 @@ public: float buffer_load () const; - void move_processor_automation (boost::weak_ptr, std::list > const&); + void move_processor_automation (boost::weak_ptr, std::list const&); /* called by the Butler in a non-realtime context as part of its normal * buffer refill loop (not due to transport-mechanism requests like @@ -151,7 +151,7 @@ protected: void resolve_tracker (Evoral::EventSink& buffer, samplepos_t time); int use_playlist (DataType, boost::shared_ptr); - void playlist_ranges_moved (std::list > const&, bool); + void playlist_ranges_moved (std::list const&, bool); int add_channel_to (boost::shared_ptr, uint32_t how_many); diff --git a/libs/ardour/ardour/disk_writer.h b/libs/ardour/ardour/disk_writer.h index f6028a5659..5307fce179 100644 --- a/libs/ardour/ardour/disk_writer.h +++ b/libs/ardour/ardour/disk_writer.h @@ -157,7 +157,7 @@ private: bool prep_record_enable (); bool prep_record_disable (); - void calculate_record_range (Evoral::OverlapType ot, samplepos_t transport_sample, + void calculate_record_range (Temporal::OverlapType ot, samplepos_t transport_sample, samplecnt_t nframes, samplecnt_t& rec_nframes, samplecnt_t& rec_offset); diff --git a/libs/ardour/ardour/ebur128_analysis.h b/libs/ardour/ardour/ebur128_analysis.h index 819d8083b2..23145d8b9f 100644 --- a/libs/ardour/ardour/ebur128_analysis.h +++ b/libs/ardour/ardour/ebur128_analysis.h @@ -33,7 +33,7 @@ public: EBUr128Analysis (float sample_rate); ~EBUr128Analysis(); - int run (Readable*); + int run (AudioReadable*); float loudness () const { return _loudness; } float loudness_range () const { return _loudness_range; } diff --git a/libs/ardour/ardour/export_channel.h b/libs/ardour/ardour/export_channel.h index 14b6533803..8345d5940c 100644 --- a/libs/ardour/ardour/export_channel.h +++ b/libs/ardour/ardour/export_channel.h @@ -125,8 +125,8 @@ class LIBARDOUR_API RegionExportChannelFactory size_t n_channels; BufferSet buffers; bool buffers_up_to_date; - samplecnt_t region_start; - samplecnt_t position; + samplepos_t region_start; + samplepos_t position; boost::scoped_array mixdown_buffer; boost::scoped_array gain_buffer; diff --git a/libs/ardour/ardour/location.h b/libs/ardour/ardour/location.h index d7c7d79869..dac9abd903 100644 --- a/libs/ardour/ardour/location.h +++ b/libs/ardour/ardour/location.h @@ -65,7 +65,7 @@ public: }; Location (Session &); - Location (Session &, samplepos_t, samplepos_t, const std::string &, Flags bits = Flags(0), const uint32_t sub_num = 0); + Location (Session &, Temporal::timepos_t const &, Temporal::timepos_t const &, const std::string &, Flags bits = Flags(0)); Location (const Location& other); Location (Session &, const XMLNode&); Location* operator= (const Location& other); @@ -77,15 +77,19 @@ public: void unlock (); int64_t timestamp() const { return _timestamp; }; - samplepos_t start() const { return _start; } - samplepos_t end() const { return _end; } - samplecnt_t length() const { return _end - _start; } + timepos_t start() const { return _start; } + timepos_t end() const { return _end; } + timecnt_t length() const { return _start.distance (_end); } - int set_start (samplepos_t s, bool force = false, bool allow_beat_recompute = true, const uint32_t sub_num = 0); - int set_end (samplepos_t e, bool force = false, bool allow_beat_recompute = true, const uint32_t sub_num = 0); - int set (samplepos_t start, samplepos_t end, bool allow_beat_recompute = true, const uint32_t sub_num = 0); + samplepos_t start_sample() const { return _start.samples(); } + samplepos_t end_sample() const { return _end.samples(); } + samplecnt_t length_samples() const { return _end.samples() - _start.samples(); } - int move_to (samplepos_t pos, const uint32_t sub_num); + int set_start (timepos_t const & s, bool force = false); + int set_end (timepos_t const & e, bool force = false); + int set (timepos_t const & start, timepos_t const & end); + + int move_to (timepos_t const & pos); const std::string& name() const { return _name; } void set_name (const std::string &str); @@ -126,7 +130,7 @@ public: static PBD::Signal1 start_changed; static PBD::Signal1 flags_changed; static PBD::Signal1 lock_changed; - static PBD::Signal1 position_lock_style_changed; + static PBD::Signal1 position_time_domain_changed; /* this is sent only when both start and end change at the same time */ static PBD::Signal1 changed; @@ -142,7 +146,7 @@ public: PBD::Signal0 StartChanged; PBD::Signal0 FlagsChanged; PBD::Signal0 LockChanged; - PBD::Signal0 PositionLockStyleChanged; + PBD::Signal0 TimeDomainChanged; /* CD Track / CD-Text info */ @@ -152,28 +156,23 @@ public: XMLNode& get_state (void); int set_state (const XMLNode&, int version); - PositionLockStyle position_lock_style() const { return _position_lock_style; } - void set_position_lock_style (PositionLockStyle ps); - void recompute_samples_from_beat (); + Temporal::TimeDomain position_time_domain() const { return _start.time_domain(); } + void set_position_time_domain (Temporal::TimeDomain ps); static PBD::Signal0 scene_changed; /* for use by backend scene change management, class level */ PBD::Signal0 SceneChangeChanged; /* for use by objects interested in this object */ private: std::string _name; - samplepos_t _start; - double _start_beat; - samplepos_t _end; - double _end_beat; + timepos_t _start; + timepos_t _end; Flags _flags; bool _locked; - PositionLockStyle _position_lock_style; boost::shared_ptr _scene_change; int64_t _timestamp; void set_mark (bool yn); bool set_flag_internal (bool yn, Flags flag); - void recompute_beat_from_samples (const uint32_t sub_num); }; /** A collection of session locations including unique dedicated locations (loop, punch, etc) */ @@ -229,7 +228,7 @@ public: samplepos_t first_mark_before (samplepos_t, bool include_special_ranges = false); samplepos_t first_mark_after (samplepos_t, bool include_special_ranges = false); - void marks_either_side (samplepos_t const, samplepos_t &, samplepos_t &) const; + void marks_either_side (timepos_t const &, timepos_t &, timepos_t &) const; /** Return range with closest start pos to the where argument * @@ -239,9 +238,9 @@ public: * * @return Location object or nil */ - Location* range_starts_at(samplepos_t pos, samplecnt_t slop = 0, bool incl = false) const; + Location* range_starts_at(samplepos_t, samplecnt_t slop = 0, bool incl = false) const; - void find_all_between (samplepos_t start, samplepos_t, LocationList&, Location::Flags); + void find_all_between (timepos_t const & start, timepos_t const & end, LocationList&, Location::Flags); PBD::Signal1 current_changed; diff --git a/libs/ardour/ardour/lua_api.h b/libs/ardour/ardour/lua_api.h index c1bd5fc9bd..38707ac245 100644 --- a/libs/ardour/ardour/lua_api.h +++ b/libs/ardour/ardour/lua_api.h @@ -36,7 +36,7 @@ #include "ardour/session.h" namespace ARDOUR { - class Readable; + class AudioReadable; } namespace ARDOUR { namespace LuaAPI { @@ -269,7 +269,7 @@ namespace ARDOUR { namespace LuaAPI { * * This interface allows to load a plugins and directly access it using the Vamp Plugin API. * - * A convenience method is provided to analyze Ardour::Readable objects (Regions). + * A convenience method is provided to analyze Ardour::AudioReadable objects (Regions). */ public: Vamp (const std::string&, float sample_rate); @@ -282,7 +282,7 @@ namespace ARDOUR { namespace LuaAPI { ::Vamp::Plugin* plugin () { return _plugin; } - /** high-level abstraction to process a single channel of the given Readable. + /** high-level abstraction to process a single channel of the given AudioReadable. * * If the plugin is not yet initialized, initialize() is called. * @@ -294,7 +294,7 @@ namespace ARDOUR { namespace LuaAPI { * @param fn lua callback function or nil * @return 0 on success */ - int analyze (boost::shared_ptr r, uint32_t channel, luabridge::LuaRef fn); + int analyze (boost::shared_ptr r, uint32_t channel, luabridge::LuaRef fn); /** call plugin():reset() and clear intialization flag */ void reset (); @@ -341,7 +341,7 @@ namespace ARDOUR { namespace LuaAPI { }; - class Rubberband : public Readable , public boost::enable_shared_from_this + class Rubberband : public AudioReadable , public boost::enable_shared_from_this { public: Rubberband (boost::shared_ptr, bool percussive); @@ -349,10 +349,10 @@ namespace ARDOUR { namespace LuaAPI { bool set_strech_and_pitch (double stretch_ratio, double pitch_ratio); bool set_mapping (luabridge::LuaRef tbl); boost::shared_ptr process (luabridge::LuaRef cb); - boost::shared_ptr readable (); + boost::shared_ptr readable (); - /* readable API */ - samplecnt_t readable_length () const { return _read_len; } + /* audioreadable API */ + samplecnt_t readable_length_samples () const { return _read_len; } uint32_t n_channels () const { return _n_channels; } samplecnt_t read (Sample*, samplepos_t pos, samplecnt_t cnt, int channel) const; diff --git a/libs/ardour/ardour/midi_cursor.h b/libs/ardour/ardour/midi_cursor.h index d7d65e6160..b8c0534b0e 100644 --- a/libs/ardour/ardour/midi_cursor.h +++ b/libs/ardour/ardour/midi_cursor.h @@ -35,7 +35,7 @@ namespace ARDOUR { struct MidiCursor : public boost::noncopyable { - MidiCursor() : last_read_end(0) {} + MidiCursor() {} void connect(PBD::Signal1& invalidated) { connections.drop_connections(); @@ -50,7 +50,7 @@ struct MidiCursor : public boost::noncopyable { Evoral::Sequence::const_iterator iter; std::set::WeakNotePtr> active_notes; - samplepos_t last_read_end; + timepos_t last_read_end; PBD::ScopedConnectionList connections; }; diff --git a/libs/ardour/ardour/midi_model.h b/libs/ardour/ardour/midi_model.h index aa650a2967..e19430c5ca 100644 --- a/libs/ardour/ardour/midi_model.h +++ b/libs/ardour/ardour/midi_model.h @@ -300,7 +300,7 @@ public: int set_state(const XMLNode&) { return 0; } PBD::Signal0 ContentsChanged; - PBD::Signal1 ContentsShifted; + PBD::Signal1 ContentsShifted; boost::shared_ptr midi_source (); void set_midi_source (boost::shared_ptr); diff --git a/libs/ardour/ardour/midi_playlist.h b/libs/ardour/ardour/midi_playlist.h index be26f54d2e..7f732648b9 100644 --- a/libs/ardour/ardour/midi_playlist.h +++ b/libs/ardour/ardour/midi_playlist.h @@ -64,8 +64,8 @@ public: /** This constructor does NOT notify others (session) */ MidiPlaylist (boost::shared_ptr other, - samplepos_t start, - samplecnt_t cnt, + timepos_t const & start, + timepos_t const & cnt, std::string name, bool hidden = false); @@ -77,7 +77,8 @@ public: int set_state (const XMLNode&, int version); bool destroy_region (boost::shared_ptr); - void _split_region (boost::shared_ptr, const MusicSample& position, ThawList& thawlist); + + void _split_region (boost::shared_ptr, timepos_t const & position, Thawlist& thawlist); void set_note_mode (NoteMode m) { _note_mode = m; } diff --git a/libs/ardour/ardour/midi_playlist_source.h b/libs/ardour/ardour/midi_playlist_source.h deleted file mode 100644 index 1d89ae87bb..0000000000 --- a/libs/ardour/ardour/midi_playlist_source.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 2011-2015 David Robillard - * Copyright (C) 2011-2017 Paul Davis - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef __ardour_midi_playlist_source_h__ -#define __ardour_midi_playlist_source_h__ - -#include - -#include - -#include "ardour/ardour.h" -#include "ardour/midi_source.h" -#include "ardour/playlist_source.h" - -namespace ARDOUR { - -class MidiPlaylist; - -class LIBARDOUR_API MidiPlaylistSource : public MidiSource, public PlaylistSource { -public: - virtual ~MidiPlaylistSource (); - - bool empty() const; - samplecnt_t length (samplepos_t) const; - - samplecnt_t read_unlocked (Sample *dst, samplepos_t start, samplecnt_t cnt) const; - samplecnt_t write_unlocked (Sample *src, samplecnt_t cnt); - - XMLNode& get_state (); - int set_state (const XMLNode&, int version); - - void append_event_beats(const Glib::Threads::Mutex::Lock& lock, const Evoral::Event& ev); - void append_event_samples(const Glib::Threads::Mutex::Lock& lock, const Evoral::Event& ev, samplepos_t source_start); - void load_model(const Glib::Threads::Mutex::Lock& lock, bool force_reload=false); - void destroy_model(const Glib::Threads::Mutex::Lock& lock); - -protected: - friend class SourceFactory; - - MidiPlaylistSource (Session&, const PBD::ID& orig, const std::string& name, boost::shared_ptr, uint32_t chn, - sampleoffset_t begin, samplecnt_t len, Source::Flag flags); - MidiPlaylistSource (Session&, const XMLNode&); - - - void flush_midi(const Lock& lock); - - samplecnt_t read_unlocked (const Lock& lock, - Evoral::EventSink& dst, - samplepos_t position, - samplepos_t start, - samplecnt_t cnt, - Evoral::Range* loop_range, - MidiStateTracker* tracker, - MidiChannelFilter* filter) const; - - samplecnt_t write_unlocked (const Lock& lock, - MidiRingBuffer& dst, - samplepos_t position, - samplecnt_t cnt); - -private: - int set_state (const XMLNode&, int version, bool with_descendants); - samplecnt_t _length; -}; - -} /* namespace */ - -#endif /* __ardour_midi_playlist_source_h__ */ diff --git a/libs/ardour/ardour/midi_region.h b/libs/ardour/ardour/midi_region.h index a5b5bc5637..ece984b8cc 100644 --- a/libs/ardour/ardour/midi_region.h +++ b/libs/ardour/ardour/midi_region.h @@ -26,7 +26,7 @@ #include #include "temporal/beats.h" -#include "evoral/Range.h" +#include "temporal/range.h" #include "pbd/string_convert.h" @@ -68,26 +68,23 @@ class LIBARDOUR_API MidiRegion : public Region boost::shared_ptr midi_source (uint32_t n=0) const; - /* Stub Readable interface */ - virtual samplecnt_t read (Sample*, samplepos_t /*pos*/, samplecnt_t /*cnt*/, int /*channel*/) const { return 0; } + timecnt_t read_at (Evoral::EventSink& dst, + timepos_t const & position, + timecnt_t const & dur, + Temporal::Range* loop_range, + MidiCursor& cursor, + uint32_t chan_n = 0, + NoteMode mode = Sustained, + MidiStateTracker* tracker = 0, + MidiChannelFilter* filter = 0) const; - samplecnt_t read_at (Evoral::EventSink& dst, - samplepos_t position, - samplecnt_t dur, - Evoral::Range* loop_range, - MidiCursor& cursor, - uint32_t chan_n = 0, - NoteMode mode = Sustained, - MidiStateTracker* tracker = 0, - MidiChannelFilter* filter = 0) const; - - samplecnt_t master_read_at (MidiRingBuffer& dst, - samplepos_t position, - samplecnt_t dur, - Evoral::Range* loop_range, - MidiCursor& cursor, - uint32_t chan_n = 0, - NoteMode mode = Sustained) const; + timecnt_t master_read_at (MidiRingBuffer& dst, + timepos_t const & position, + timecnt_t const & dur, + Temporal::Range* loop_range, + MidiCursor& cursor, + uint32_t chan_n = 0, + NoteMode mode = Sustained) const; XMLNode& state (); int set_state (const XMLNode&, int version); @@ -127,38 +124,30 @@ class LIBARDOUR_API MidiRegion : public Region MidiRegion (boost::shared_ptr); MidiRegion (boost::shared_ptr, timecnt_t const & offset); - samplecnt_t _read_at (const SourceList&, Evoral::EventSink& dst, - samplepos_t position, - samplecnt_t dur, - Evoral::Range* loop_range, - MidiCursor& cursor, - uint32_t chan_n = 0, - NoteMode mode = Sustained, - MidiStateTracker* tracker = 0, - MidiChannelFilter* filter = 0) const; + timecnt_t _read_at (const SourceList&, Evoral::EventSink& dst, + timepos_t const & position, + timecnt_t const & dur, + Temporal::Range* loop_range, + MidiCursor& cursor, + uint32_t chan_n = 0, + NoteMode mode = Sustained, + MidiStateTracker* tracker = 0, + MidiChannelFilter* filter = 0) const; void register_properties (); - void post_set (const PBD::PropertyChange&); void recompute_at_start (); void recompute_at_end (); bool set_name (const std::string & str); - void set_position_internal (timepos_t const & pos); - void set_length_internal (timecnt_t const & len); void set_start_internal (timecnt_t const &); - void trim_to_internal (timepos_t const & position, timecnt_t const & length); - void update_length_beats (); void model_changed (); void model_contents_changed (); - void model_shifted (double qn_distance); + void model_shifted (timecnt_t qn_distance); void model_automation_state_changed (Evoral::Parameter const &); - void set_start_beats_from_start_samples (); - void update_after_tempo_map_change (bool send_change = true); - std::set _filtered_parameters; ///< parameters that we ask our source not to return when reading PBD::ScopedConnection _model_connection; PBD::ScopedConnection _model_shift_connection; diff --git a/libs/ardour/ardour/midi_source.h b/libs/ardour/ardour/midi_source.h index a330825081..fac555495d 100644 --- a/libs/ardour/ardour/midi_source.h +++ b/libs/ardour/ardour/midi_source.h @@ -27,10 +27,14 @@ #include #include #include + #include "pbd/stateful.h" #include "pbd/xml++.h" + #include "evoral/Sequence.h" -#include "evoral/Range.h" + +#include "temporal/range.h" + #include "ardour/ardour.h" #include "ardour/buffer.h" #include "ardour/midi_cursor.h" @@ -95,21 +99,17 @@ class LIBARDOUR_API MidiSource : virtual public Source * @param filter Channel filter to apply or NULL to disable filter * @param tracker an optional pointer to MidiStateTracker object, for note on/off tracking. * @param filtered Parameters whose MIDI messages will not be returned. - * @param pos_beats Start position (quarter note = \p pos_beats - \p start_beats) - * @param start_beats Start position offset */ - virtual samplecnt_t midi_read (const Lock& lock, - Evoral::EventSink& dst, - samplepos_t source_start, - samplepos_t start, - samplecnt_t cnt, - Evoral::Range* loop_range, - MidiCursor& cursor, - MidiStateTracker* tracker, - MidiChannelFilter* filter, - const std::set& filtered, - const double pos_beats, - const double start_beats) const; + virtual timecnt_t midi_read (const Lock& lock, + Evoral::EventSink& dst, + timepos_t const & source_start, + timecnt_t const & start, + timecnt_t const & cnt, + Temporal::Range* loop_range, + MidiCursor& cursor, + MidiStateTracker* tracker, + MidiChannelFilter* filter, + const std::set& filtered); /** Write data from a MidiRingBuffer to this source. * @param lock Reference to the Mutex to lock before modification @@ -117,10 +117,10 @@ class LIBARDOUR_API MidiSource : virtual public Source * @param source_start This source's start position in session samples. * @param cnt The length of time to write. */ - virtual samplecnt_t midi_write (const Lock& lock, - MidiRingBuffer& source, - samplepos_t source_start, - samplecnt_t cnt); + virtual timecnt_t midi_write (const Lock& lock, + MidiRingBuffer& source, + timepos_t const & source_start, + timecnt_t const & cnt); /** Append a single event with a timestamp in beats. * @@ -137,10 +137,6 @@ class LIBARDOUR_API MidiSource : virtual public Source const Evoral::Event& ev, samplepos_t source_start) = 0; - virtual bool empty () const; - virtual samplecnt_t length (samplepos_t pos) const; - virtual void update_length (samplecnt_t); - virtual void mark_streaming_midi_write_started (const Lock& lock, NoteMode mode); virtual void mark_streaming_write_started (const Lock& lock); virtual void mark_streaming_write_completed (const Lock& lock); @@ -216,14 +212,14 @@ class LIBARDOUR_API MidiSource : virtual public Source protected: virtual void flush_midi(const Lock& lock) = 0; - virtual samplecnt_t read_unlocked (const Lock& lock, - Evoral::EventSink& dst, - samplepos_t position, - samplepos_t start, - samplecnt_t cnt, - Evoral::Range* loop_range, - MidiStateTracker* tracker, - MidiChannelFilter* filter) const = 0; + virtual timecnt_t read_unlocked (const Lock& lock, + Evoral::EventSink& dst, + timepos_t const & position, + timecnt_t const & start, + timecnt_t const & cnt, + Temporal::Range* loop_range, + MidiStateTracker* tracker, + MidiChannelFilter* filter) const = 0; /** Write data to this source from a MidiRingBuffer. * @param lock Reference to the Mutex to lock before modification @@ -231,10 +227,10 @@ class LIBARDOUR_API MidiSource : virtual public Source * @param position This source's start position in session samples. * @param cnt The duration of this block to write for. */ - virtual samplecnt_t write_unlocked (const Lock& lock, - MidiRingBuffer& source, - samplepos_t position, - samplecnt_t cnt) = 0; + virtual timecnt_t write_unlocked (const Lock& lock, + MidiRingBuffer& source, + timepos_t const & position, + timecnt_t const & cnt) = 0; boost::shared_ptr _model; bool _writing; diff --git a/libs/ardour/ardour/onset_detector.h b/libs/ardour/ardour/onset_detector.h index 9b2a407619..b5e64d16a5 100644 --- a/libs/ardour/ardour/onset_detector.h +++ b/libs/ardour/ardour/onset_detector.h @@ -40,7 +40,7 @@ public: void set_minioi (float); void set_function (int); - int run (const std::string& path, Readable*, uint32_t channel, AnalysisFeatureList& results); + int run (const std::string& path, AudioReadable*, uint32_t channel, AnalysisFeatureList& results); static void cleanup_onsets (AnalysisFeatureList&, float sr, float gap_msecs); diff --git a/libs/ardour/ardour/pan_controllable.h b/libs/ardour/ardour/pan_controllable.h index c72f0dbe45..988492972f 100644 --- a/libs/ardour/ardour/pan_controllable.h +++ b/libs/ardour/ardour/pan_controllable.h @@ -37,11 +37,12 @@ class Pannable; class LIBARDOUR_API PanControllable : public AutomationControl { public: +#warning NUTEMPO QUESTION what time domain shoudl this really use? PanControllable (Session& s, std::string name, Pannable* o, Evoral::Parameter param) : AutomationControl (s, param, ParameterDescriptor(param), - boost::shared_ptr(new AutomationList(param)), + boost::shared_ptr(new AutomationList(param, Temporal::AudioTime)), name) , owner (o) {} diff --git a/libs/ardour/ardour/pannable.h b/libs/ardour/ardour/pannable.h index 9aff50d118..092946b493 100644 --- a/libs/ardour/ardour/pannable.h +++ b/libs/ardour/ardour/pannable.h @@ -64,9 +64,11 @@ public: return ((_auto_state & Write) || ((_auto_state & (Touch | Latch)) && touching())); } - void start_touch (double when); - void stop_touch (double when); + void start_touch (timepos_t const & when); + void stop_touch (timepos_t const & when); + bool touching() const { return g_atomic_int_get (&_touching); } + bool writing() const { return _auto_state == Write; } bool touch_enabled() const { return _auto_state & (Touch | Latch); } diff --git a/libs/ardour/ardour/playlist.h b/libs/ardour/ardour/playlist.h index 034c769dcb..9dd02a0fba 100644 --- a/libs/ardour/ardour/playlist.h +++ b/libs/ardour/ardour/playlist.h @@ -46,7 +46,7 @@ #include "pbd/undo.h" #include "pbd/g_atomic_compat.h" -#include "evoral/Range.h" +#include "temporal/range.h" #include "ardour/ardour.h" #include "ardour/data_type.h" @@ -95,7 +95,7 @@ public: Playlist (Session&, const XMLNode&, DataType type, bool hidden = false); Playlist (Session&, std::string name, DataType type, bool hidden = false); Playlist (boost::shared_ptr, std::string name, bool hidden = false); - Playlist (boost::shared_ptr, samplepos_t start, samplecnt_t cnt, std::string name, bool hidden = false); + Playlist (boost::shared_ptr, timepos_t const & start, timepos_t const & cnt, std::string name, bool hidden = false); virtual ~Playlist (); @@ -159,51 +159,54 @@ public: bool shared_with (const PBD::ID&) const; void reset_shares (); - uint32_t n_regions () const; - bool all_regions_empty () const; - std::pair get_extent () const; - std::pair get_extent_with_endspace () const; - layer_t top_layer () const; + uint32_t n_regions() const; + bool all_regions_empty() const; + std::pair get_extent () const; + std::pair get_extent_with_endspace() const; + layer_t top_layer() const; + + EditMode get_edit_mode() const { return _edit_mode; } + void set_edit_mode (EditMode); /* Editing operations */ - void add_region (boost::shared_ptr, samplepos_t position, float times = 1, bool auto_partition = false, int32_t sub_num = 0, double quarter_note = 0.0, bool for_music = false); + void add_region (boost::shared_ptr, timepos_t const & position, float times = 1, bool auto_partition = false); void remove_region (boost::shared_ptr); void get_equivalent_regions (boost::shared_ptr, std::vector >&); - void replace_region (boost::shared_ptr old, boost::shared_ptr newr, samplepos_t pos); - void split_region (boost::shared_ptr, const MusicSample& position); - void split (const MusicSample& at); - void shift (samplepos_t at, sampleoffset_t distance, bool move_intersected, bool ignore_music_glue); - void partition (samplepos_t start, samplepos_t end, bool cut = false); - void duplicate (boost::shared_ptr, samplepos_t position, float times); - void duplicate (boost::shared_ptr, samplepos_t position, samplecnt_t gap, float times); - void duplicate_until (boost::shared_ptr, samplepos_t position, samplecnt_t gap, samplepos_t end); - void duplicate_range (AudioRange&, float times); - void duplicate_ranges (std::list&, float times); - void nudge_after (samplepos_t start, samplecnt_t distance, bool forwards); - void fade_range (std::list&); - void remove_gaps (samplepos_t gap_threshold, samplepos_t leave_gap, boost::function gap_callback); + void get_region_list_equivalent_regions (boost::shared_ptr, std::vector >&); + void get_source_equivalent_regions (boost::shared_ptr, std::vector >&); + void replace_region (boost::shared_ptr old, boost::shared_ptr newr, timepos_t const & pos); + void split_region (boost::shared_ptr, timepos_t const & position); + void split (timepos_t const & at); + void shift (timepos_t const & at, timecnt_t const & distance, bool move_intersected, bool ignore_music_glue); + void partition (timepos_t const & start, timepos_t const & end, bool cut = false); + void duplicate (boost::shared_ptr, timepos_t & position, float times); + void duplicate (boost::shared_ptr, timepos_t & position, timecnt_t const & gap, float times); + void duplicate_until (boost::shared_ptr, timepos_t & position, timecnt_t const & gap, timepos_t const & end); + void duplicate_range (TimelineRange&, float times); + void duplicate_ranges (std::list&, float times); + void nudge_after (timepos_t const & start, timecnt_t const & distance, bool forwards); boost::shared_ptr combine (const RegionList&); - void uncombine (boost::shared_ptr); + void uncombine (boost::shared_ptr); + void fade_range (std::list&); void shuffle (boost::shared_ptr, int dir); - void ripple (samplepos_t at, samplecnt_t distance, RegionList* exclude); - void ripple (samplepos_t at, samplecnt_t distance, boost::shared_ptr exclude) - { - RegionList el; - if (exclude) { - el.push_back (exclude); - } - ripple (at, distance, &el); + void ripple (timepos_t const & at, timecnt_t const & distance, RegionList *exclude); + void ripple (timepos_t const & at, timecnt_t const & distance, boost::shared_ptr exclude) { + RegionList el; + if (exclude) { + el.push_back (exclude); + } + ripple (at, distance, &el); } void update_after_tempo_map_change (); - boost::shared_ptr cut (std::list&, bool result_is_hidden = true); - boost::shared_ptr copy (std::list&, bool result_is_hidden = true); - int paste (boost::shared_ptr, samplepos_t position, float times, const int32_t sub_num); + boost::shared_ptr cut (std::list&, bool result_is_hidden = true); + boost::shared_ptr copy (std::list&, bool result_is_hidden = true); + int paste (boost::shared_ptr, timepos_t const & position, float times); const RegionListProperty& region_list_property () const { @@ -212,31 +215,31 @@ public: boost::shared_ptr region_list (); - boost::shared_ptr regions_at (samplepos_t sample); - uint32_t count_regions_at (samplepos_t) const; + boost::shared_ptr regions_at (timepos_t const & sample); + uint32_t count_regions_at (timepos_t const &) const; /** @param start Range start. * @param end Range end. * @return regions which have some part within this range. */ - boost::shared_ptr regions_touched (samplepos_t start, samplepos_t end); - boost::shared_ptr regions_with_start_within (Evoral::Range); - boost::shared_ptr regions_with_end_within (Evoral::Range); - uint32_t region_use_count (boost::shared_ptr) const; - boost::shared_ptr find_region (const PBD::ID&) const; - boost::shared_ptr top_region_at (samplepos_t sample); - boost::shared_ptr top_unmuted_region_at (samplepos_t sample); - boost::shared_ptr find_next_region (samplepos_t sample, RegionPoint point, int dir); - samplepos_t find_next_region_boundary (samplepos_t sample, int dir); - bool region_is_shuffle_constrained (boost::shared_ptr); - bool has_region_at (samplepos_t const) const; + boost::shared_ptr regions_touched (timepos_t const & start, timepos_t const & end); + boost::shared_ptr regions_with_start_within (Temporal::TimeRange); + boost::shared_ptr regions_with_end_within (Temporal::TimeRange); + uint32_t region_use_count (boost::shared_ptr) const; + boost::shared_ptr find_region (const PBD::ID&) const; + boost::shared_ptr top_region_at (timepos_t const &); + boost::shared_ptr top_unmuted_region_at (timepos_t const &); + boost::shared_ptr find_next_region (timepos_t const &, RegionPoint point, int dir); + timepos_t find_next_region_boundary (timepos_t const &, int dir); + bool region_is_shuffle_constrained (boost::shared_ptr); + bool has_region_at (timepos_t const &) const; samplepos_t find_prev_region_start (samplepos_t sample); bool uses_source (boost::shared_ptr src, bool shallow = false) const; void deep_sources (std::set >&) const; - samplepos_t find_next_transient (samplepos_t position, int dir); + samplepos_t find_next_transient (timepos_t const & position, int dir); void foreach_region (boost::function)>); @@ -252,12 +255,12 @@ public: PBD::Signal0 LayeringChanged; /** Emitted when regions have moved (not when regions have only been trimmed) */ - PBD::Signal2 > const&, bool> RangesMoved; + PBD::Signal2 const &, bool> RangesMoved; /** Emitted when regions are extended; the ranges passed are the new extra time ranges that these regions now occupy. */ - PBD::Signal1 > const&> RegionsExtended; + PBD::Signal1 const &> RegionsExtended; static std::string bump_name (std::string old_name, Session&); @@ -289,11 +292,8 @@ public: return boost::shared_ptr (); } - samplepos_t find_next_top_layer_position (samplepos_t) const; - uint32_t combine_ops () const - { - return _combine_ops; - } + timepos_t find_next_top_layer_position (timepos_t const &) const; + uint32_t combine_ops() const { return _combine_ops; } void set_layer (boost::shared_ptr, double); @@ -373,6 +373,7 @@ protected: * region trims are not included in this list; it is used to * do automation-follows-regions. */ + std::list > pending_range_moves; /** Extra sections added to regions during trims */ @@ -393,6 +394,7 @@ protected: uint32_t subcnt; PBD::ID _orig_track_id; uint32_t _combine_ops; + std::list _shared_with_ids; void init (bool hide); @@ -410,7 +412,7 @@ protected: void _set_sort_id (); - boost::shared_ptr regions_touched_locked (samplepos_t start, samplepos_t end); + boost::shared_ptr regions_touched_locked (timepos_t const & start, timepos_t const & end); void notify_region_removed (boost::shared_ptr); void notify_region_added (boost::shared_ptr); @@ -431,34 +433,34 @@ protected: void sort_regions (); - - void ripple_locked (samplepos_t at, samplecnt_t distance, RegionList* exclude); - bool ripple_unlocked (samplepos_t at, samplecnt_t distance, RegionList* exclude, ThawList& thawlist); + void ripple_locked (timepos_t const & at, timecnt_t const & distance, RegionList *exclude); + void ripple_unlocked (timepos_t const & at, timecnt_t const & distance, RegionList *exclude, Thawlist& thawlist); virtual void remove_dependents (boost::shared_ptr /*region*/) {} virtual void region_going_away (boost::weak_ptr /*region*/) {} virtual XMLNode& state (bool); - bool add_region_internal (boost::shared_ptr, samplepos_t position, ThawList& thawlist, int32_t sub_num = 0, double quarter_note = 0.0, bool for_music = false); + bool add_region_internal (boost::shared_ptr, timepos_t const & position, Thawlist& thawlist); int remove_region_internal (boost::shared_ptr, ThawList& thawlist); void copy_regions (RegionList&) const; - void partition_internal (samplepos_t start, samplepos_t end, bool cutting, ThawList& thawlist); - std::pair _get_extent () const; + void partition_internal (timepos_t const & start, timepos_t const & end, bool cutting, ThawList& thawlist); - boost::shared_ptr cut_copy (boost::shared_ptr (Playlist::*pmf) (samplepos_t, samplecnt_t, bool), - std::list& ranges, bool result_is_hidden); - boost::shared_ptr cut (samplepos_t start, samplecnt_t cnt, bool result_is_hidden); - boost::shared_ptr copy (samplepos_t start, samplecnt_t cnt, bool result_is_hidden); + std::pair _get_extent() const; + + boost::shared_ptr cut_copy (boost::shared_ptr (Playlist::*pmf)(timepos_t const &, timecnt_t const &, bool), + std::list& ranges, bool result_is_hidden); + boost::shared_ptr cut (timepos_t const & start, timecnt_t const & cnt, bool result_is_hidden); + boost::shared_ptr copy (timepos_t const & start, timecnt_t const & cnt, bool result_is_hidden); void relayer (); void begin_undo (); void end_undo (); - virtual void _split_region (boost::shared_ptr, const MusicSample& position, ThawList& thawlist); + virtual void _split_region (boost::shared_ptr, timepos_t const & position, Thawlist& thawlist); typedef std::pair, boost::shared_ptr > TwoRegions; @@ -479,15 +481,13 @@ private: private: void freeze_locked (); - void setup_layering_indices (RegionList const&); - void coalesce_and_check_crossfades (std::list >); + void setup_layering_indices (RegionList const &); + void coalesce_and_check_crossfades (std::list); + boost::shared_ptr find_regions_at (timepos_t const &); - boost::shared_ptr find_regions_at (samplepos_t); - - mutable boost::optional > _cached_extent; - - samplepos_t _end_space; // this is used when we are pasting a range with extra space at the end - bool _playlist_shift_active; + mutable boost::optional > _cached_extent; + timepos_t _end_space; //this is used when we are pasting a range with extra space at the end + bool _playlist_shift_active; std::string _pgroup_id; // when we make multiple playlists in one action, they will share the same pgroup_id }; @@ -495,3 +495,4 @@ private: } /* namespace ARDOUR */ #endif /* __ardour_playlist_h__ */ + diff --git a/libs/ardour/ardour/playlist_factory.h b/libs/ardour/ardour/playlist_factory.h index 76e13d921a..c9a015cdf2 100644 --- a/libs/ardour/ardour/playlist_factory.h +++ b/libs/ardour/ardour/playlist_factory.h @@ -37,7 +37,7 @@ class LIBARDOUR_API PlaylistFactory { static boost::shared_ptr create (Session&, const XMLNode&, bool hidden = false, bool unused = false); static boost::shared_ptr create (DataType type, Session&, std::string name, bool hidden = false); static boost::shared_ptr create (boost::shared_ptr, std::string name, bool hidden = false); - static boost::shared_ptr create (boost::shared_ptr, samplepos_t start, samplecnt_t cnt, std::string name, bool hidden = false); + static boost::shared_ptr create (boost::shared_ptr, timepos_t const & start, timepos_t const & cnt, std::string name, bool hidden = false); }; } diff --git a/libs/ardour/ardour/playlist_source.h b/libs/ardour/ardour/playlist_source.h index 001c8f97a7..90fe5a3a66 100644 --- a/libs/ardour/ardour/playlist_source.h +++ b/libs/ardour/ardour/playlist_source.h @@ -45,11 +45,11 @@ protected: boost::shared_ptr _playlist; PBD::ID _original; PBD::ID _owner; - sampleoffset_t _playlist_offset; - samplecnt_t _playlist_length; + timepos_t _playlist_offset; + timepos_t _playlist_length; PlaylistSource (Session&, const PBD::ID&, const std::string& name, boost::shared_ptr, DataType, - sampleoffset_t begin, samplecnt_t len, Source::Flag flags); + timepos_t const & begin, timepos_t const & len, Source::Flag flags); PlaylistSource (Session&, const XMLNode&); void add_state (XMLNode&); diff --git a/libs/ardour/ardour/plugin_insert.h b/libs/ardour/ardour/plugin_insert.h index e992416333..7f5583b1d4 100644 --- a/libs/ardour/ardour/plugin_insert.h +++ b/libs/ardour/ardour/plugin_insert.h @@ -88,7 +88,7 @@ public: bool write_immediate_event (Evoral::EventType event_type, size_t size, const uint8_t* buf); void automation_run (samplepos_t, pframes_t, bool only_active = false); - bool find_next_event (double, double, Evoral::ControlEvent&, bool only_active = true) const; + bool find_next_event (Temporal::timepos_t const &, Temporal::timepos_t const &, Evoral::ControlEvent&, bool only_active = true) const; int set_block_size (pframes_t nframes); diff --git a/libs/ardour/ardour/quantize.h b/libs/ardour/ardour/quantize.h index ba38ea2018..a28cd1f980 100644 --- a/libs/ardour/ardour/quantize.h +++ b/libs/ardour/ardour/quantize.h @@ -29,7 +29,7 @@ namespace ARDOUR { class LIBARDOUR_API Quantize : public MidiOperator { public: Quantize (bool snap_start, bool snap_end, - double start_grid, double end_grid, + int start_grid, int end_grid, float strength, float swing, Temporal::Beats const & threshold); ~Quantize (); @@ -41,8 +41,8 @@ public: private: bool _snap_start; bool _snap_end; - double _start_grid; - double _end_grid; + int _start_grid; + int _end_grid; float _strength; float _swing; Temporal::Beats _threshold; diff --git a/libs/ardour/ardour/readable.h b/libs/ardour/ardour/readable.h index 2ac8c77ae0..912aff036d 100644 --- a/libs/ardour/ardour/readable.h +++ b/libs/ardour/ardour/readable.h @@ -27,11 +27,11 @@ namespace ARDOUR { class Session; -class LIBARDOUR_API Readable { +class LIBARDOUR_API AudioReadable { public: - virtual ~Readable() {} + virtual ~AudioReadable() {} - static std::vector > + static std::vector > load (Session&, std::string const&); virtual samplecnt_t read (Sample*, samplepos_t pos, samplecnt_t cnt, int channel) const = 0; diff --git a/libs/ardour/ardour/region.h b/libs/ardour/ardour/region.h index 5a7aee18e1..378db8c5c7 100644 --- a/libs/ardour/ardour/region.h +++ b/libs/ardour/ardour/region.h @@ -71,7 +71,6 @@ namespace Properties { LIBARDOUR_API extern PBD::PropertyDescriptor ancestral_length; LIBARDOUR_API extern PBD::PropertyDescriptor stretch; LIBARDOUR_API extern PBD::PropertyDescriptor shift; - LIBARDOUR_API extern PBD::PropertyDescriptor position_lock_style; LIBARDOUR_API extern PBD::PropertyDescriptor layering_index; LIBARDOUR_API extern PBD::PropertyDescriptor tags; LIBARDOUR_API extern PBD::PropertyDescriptor contents; // type doesn't matter here @@ -92,7 +91,6 @@ enum LIBARDOUR_API RegionEditState { class LIBARDOUR_API Region : public SessionObject , public boost::enable_shared_from_this - , public Readable , public Trimmable , public Movable { @@ -123,6 +121,7 @@ public: timecnt_t nt_start () const { return _start.val(); } timecnt_t nt_length () const { return _length.val(); } timepos_t nt_end() const; + timepos_t nt_last() const { return nt_end().decrement(); } timepos_t source_position () const; timepos_t source_relative_position (Temporal::timepos_t const &) const; @@ -132,8 +131,6 @@ public: samplecnt_t start_sample () const { return _start.val().samples(); } samplecnt_t length_samples () const { return _length.val().samples(); } - samplecnt_t readable_length_samples() const { return length_samples(); } - layer_t layer () const { return _layer; } void set_selected_for_solo(bool yn); @@ -180,7 +177,11 @@ public: } Temporal::TimeRange range_samples () const { - return Temporal::TimeRange (timepos_t::from_samples (first_sample()), timepos_t::from_samples (first_sample() + length_samples())); + return Temporal::TimeRange (timepos_t (first_sample()), timepos_t (first_sample() + length_samples())); + } + + Temporal::TimeRange range () const { + return Temporal::TimeRange (nt_position(), nt_position() + nt_length()); } bool hidden () const { return _hidden; } @@ -199,9 +200,9 @@ public: Trimmable::CanTrim can_trim () const; - PositionLockStyle position_lock_style () const { return _position_lock_style; } - void set_position_lock_style (PositionLockStyle ps); - void recompute_position_from_lock_style (); + Temporal::TimeDomain position_time_domain () const; + void set_position_time_domain (Temporal::TimeDomain ps); + void recompute_position_from_time_domain (); void suspend_property_changes (); @@ -209,14 +210,18 @@ public: return first_sample() <= sample && sample <= last_sample(); } + bool covers (timepos_t const & pos) const { + return nt_position() <= pos && pos <= nt_last(); + } + /** @return coverage of this region with the given range; * OverlapInternal: the range is internal to this region. * OverlapStart: the range overlaps the start of this region. * OverlapEnd: the range overlaps the end of this region. * OverlapExternal: the range overlaps all of this region. */ - Evoral::OverlapType coverage (samplepos_t start, samplepos_t end) const { - return Evoral::coverage (first_sample(), last_sample(), start, end); + Temporal::OverlapType coverage (timepos_t const & start, timepos_t const & end) const { + return Temporal::coverage_exclusive_ends (_position.val(), nt_last(), start, end); } bool exact_equivalent (boost::shared_ptr) const; @@ -283,7 +288,6 @@ public: bool is_compound () const; boost::shared_ptr source (uint32_t n=0) const { return _sources[ (n < _sources.size()) ? n : 0 ]; } - uint32_t n_channels() const { return _sources.size(); } SourceList& sources_for_edit () { return _sources; } const SourceList& sources () const { return _sources; } @@ -415,7 +419,6 @@ protected: void send_change (const PBD::PropertyChange&); virtual int _set_state (const XMLNode&, int version, PBD::PropertyChange& what_changed, bool send_signal); - void post_set (const PBD::PropertyChange&); virtual void set_position_internal (timepos_t const & pos); virtual void set_length_internal (timecnt_t const &); virtual void set_start_internal (timecnt_t const &); @@ -458,7 +461,7 @@ protected: private: void mid_thaw (const PBD::PropertyChange&); - virtual void trim_to_internal (timepos_t const & position, timecnt_t const & length); + void trim_to_internal (timepos_t const & position, timecnt_t const & length); void modify_front (timepos_t const & new_position, bool reset_fade); void modify_end (timepos_t const & new_position, bool reset_fade); @@ -485,7 +488,6 @@ private: PBD::Property _ancestral_length; PBD::Property _stretch; PBD::Property _shift; - PBD::EnumProperty _position_lock_style; PBD::Property _layering_index; PBD::Property _tags; PBD::Property _contents; // type is irrelevant diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h index e3cb63e481..f508182e2e 100644 --- a/libs/ardour/ardour/route.h +++ b/libs/ardour/ardour/route.h @@ -165,7 +165,7 @@ public: /* end of vfunc-based API */ - void shift (samplepos_t, samplecnt_t); + void shift (timepos_t const &, timecnt_t const &); /* controls use set_solo() to modify this route's solo state */ diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index f00b0b6161..e482dc1e81 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -66,7 +66,7 @@ #include "lua/luastate.h" -#include "evoral/Range.h" +#include "temporal/range.h" #include "midi++/types.h" #include "midi++/mmc.h" @@ -336,7 +336,7 @@ public: StripableList get_stripables () const; boost::shared_ptr get_tracks() const; boost::shared_ptr get_routes_with_internal_returns() const; - boost::shared_ptr get_routes_with_regions_at (samplepos_t const) const; + boost::shared_ptr get_routes_with_regions_at (timepos_t const &) const; boost::shared_ptr get_nth_audio_track (uint32_t) const; @@ -528,7 +528,7 @@ public: void set_auto_punch_location (Location *); void set_auto_loop_location (Location *); - void set_session_extents (samplepos_t start, samplepos_t end); + void set_session_extents (timepos_t const & start, timepos_t const & end); bool session_range_is_free () const { return _session_range_is_free; } void set_session_range_is_free (bool); @@ -1122,11 +1122,11 @@ public: /* ranges */ - void request_play_range (std::list*, bool leave_rolling = false); + void request_play_range (std::list*, bool leave_rolling = false); void request_cancel_play_range (); bool get_play_range () const { return _play_range; } - void maybe_update_session_range (samplepos_t, samplepos_t); + void maybe_update_session_range (timepos_t const &, timepos_t const &); /* preroll */ samplecnt_t preroll_samples (samplepos_t) const; @@ -1311,7 +1311,7 @@ public: void import_pt_sources (PTFFormat& ptf, ImportStatus& status); void import_pt_rest (PTFFormat& ptf); - bool import_sndfile_as_region (std::string path, SrcQuality quality, samplepos_t& pos, SourceList& sources, ImportStatus& status, uint32_t current, uint32_t total); + bool import_sndfile_as_region (std::string path, SrcQuality quality, timepos_t& pos, SourceList& sources, ImportStatus& status, uint32_t current, uint32_t total); struct ptflookup { uint16_t index1; @@ -1965,8 +1965,8 @@ private: void remove_playlist (boost::weak_ptr); void track_playlist_changed (boost::weak_ptr); void playlist_region_added (boost::weak_ptr); - void playlist_ranges_moved (std::list > const &); - void playlist_regions_extended (std::list > const &); + void playlist_ranges_moved (std::list const &); + void playlist_regions_extended (std::list const &); /* CURVES and AUTOMATION LISTS */ std::map automation_lists; @@ -2106,16 +2106,16 @@ private: /* range playback */ - std::list current_audio_range; + std::list current_audio_range; bool _play_range; - void set_play_range (std::list&, bool leave_rolling); + void set_play_range (std::list&, bool leave_rolling); void unset_play_range (); /* temporary hacks to allow selection to be pushed from GUI into backend Whenever we move the selection object into libardour, these will go away. */ - Evoral::Range _range_selection; - Evoral::Range _object_selection; + Temporal::Range _range_selection; + Temporal::Range _object_selection; void unset_preroll_record_trim (); diff --git a/libs/ardour/ardour/session_event.h b/libs/ardour/ardour/session_event.h index 2e3d02955c..9167838d4f 100644 --- a/libs/ardour/ardour/session_event.h +++ b/libs/ardour/ardour/session_event.h @@ -114,8 +114,8 @@ public: RTeventCallback rt_return; /* called after rt_slot, with this event as an argument */ PBD::EventLoop* event_loop; - std::list audio_range; - std::list music_range; + std::list audio_range; + std::list music_range; boost::shared_ptr region; boost::shared_ptr transport_master; diff --git a/libs/ardour/ardour/silentfilesource.h b/libs/ardour/ardour/silentfilesource.h index 53167b6f1a..3297e0b2c1 100644 --- a/libs/ardour/ardour/silentfilesource.h +++ b/libs/ardour/ardour/silentfilesource.h @@ -54,7 +54,7 @@ protected: } samplecnt_t read_unlocked (Sample *dst, samplepos_t start, samplecnt_t cnt) const { - cnt = std::min (cnt, std::max (0, _length - start)); + cnt = std::min (cnt, std::max (0, _length.samples() - start)); memset (dst, 0, sizeof (Sample) * cnt); return cnt; } diff --git a/libs/ardour/ardour/slavable_automation_control.h b/libs/ardour/ardour/slavable_automation_control.h index d5cf935fdc..ff0ce07f54 100644 --- a/libs/ardour/ardour/slavable_automation_control.h +++ b/libs/ardour/ardour/slavable_automation_control.h @@ -76,13 +76,13 @@ public: int set_state (XMLNode const&, int); XMLNode& get_state(); - bool find_next_event (double n, double e, Evoral::ControlEvent& ev) const + bool find_next_event (Temporal::timepos_t const & n, Temporal::timepos_t const & e, Evoral::ControlEvent& ev) const { Glib::Threads::RWLock::ReaderLock lm (master_lock); return find_next_event_locked (n, e, ev); } - bool find_next_event_locked (double now, double end, Evoral::ControlEvent& next_event) const; + bool find_next_event_locked (Temporal::timepos_t const & now, Temporal::timepos_t const & end, Evoral::ControlEvent& next_event) const; protected: @@ -136,7 +136,7 @@ protected: void update_boolean_masters_records (boost::shared_ptr); virtual bool get_masters_curve_locked (samplepos_t, samplepos_t, float*, samplecnt_t) const; - bool masters_curve_multiply (samplepos_t, samplepos_t, float*, samplecnt_t) const; + bool masters_curve_multiply (timepos_t const &, timepos_t const &, float*, samplecnt_t) const; virtual double reduce_by_masters_locked (double val, bool) const; virtual double scale_automation_callback (double val, double ratio) const; diff --git a/libs/ardour/ardour/smf_source.h b/libs/ardour/ardour/smf_source.h index 12ec5271e2..d8407ddcd3 100644 --- a/libs/ardour/ardour/smf_source.h +++ b/libs/ardour/ardour/smf_source.h @@ -80,34 +80,33 @@ public: private: bool _open; - Temporal::Beats _last_ev_time_beats; - samplepos_t _last_ev_time_samples; + Temporal::Beats _last_ev_time_beats; + samplepos_t _last_ev_time_samples; /** end time (start + duration) of last call to read_unlocked */ - mutable samplepos_t _smf_last_read_end; + mutable timecnt_t _smf_last_read_end; /** time (in SMF ticks, 1 tick per _ppqn) of the last event read by read_unlocked */ - mutable samplepos_t _smf_last_read_time; + mutable timepos_t _smf_last_read_time; int open_for_write (); void ensure_disk_file (const Lock& lock); - samplecnt_t read_unlocked (const Lock& lock, - Evoral::EventSink& dst, - samplepos_t position, - samplepos_t start, - samplecnt_t cnt, - Evoral::Range* loop_range, - MidiStateTracker* tracker, - MidiChannelFilter* filter) const; + timecnt_t read_unlocked (const Lock& lock, + Evoral::EventSink& dst, + timepos_t const & position, + timecnt_t const & start, + timecnt_t const & cnt, + Temporal::Range* loop_range, + MidiStateTracker* tracker, + MidiChannelFilter* filter) const; - samplecnt_t write_unlocked (const Lock& lock, - MidiRingBuffer& src, - samplepos_t position, - samplecnt_t cnt); + timecnt_t write_unlocked (const Lock& lock, + MidiRingBuffer& src, + timepos_t const & position, + timecnt_t const & cnt); }; }; /* namespace ARDOUR */ #endif /* __ardour_smf_source_h__ */ - diff --git a/libs/ardour/ardour/sndfilesource.h b/libs/ardour/ardour/sndfilesource.h index be14e758c3..64ceb3ec01 100644 --- a/libs/ardour/ardour/sndfilesource.h +++ b/libs/ardour/ardour/sndfilesource.h @@ -94,7 +94,7 @@ class LIBARDOUR_API SndFileSource : public AudioFileSource { int setup_broadcast_info (samplepos_t when, struct tm&, time_t); void file_closed (); - void set_natural_position (samplepos_t); + void set_natural_position (timepos_t const &); samplecnt_t nondestructive_write_unlocked (Sample *dst, samplecnt_t cnt); PBD::ScopedConnection header_position_connection; }; diff --git a/libs/ardour/ardour/source.h b/libs/ardour/ardour/source.h index 567a421b32..415313f75d 100644 --- a/libs/ardour/ardour/source.h +++ b/libs/ardour/ardour/source.h @@ -74,9 +74,11 @@ public: time_t timestamp() const { return _timestamp; } void stamp (time_t when) { _timestamp = when; } - virtual bool empty () const = 0; - virtual samplecnt_t length (samplepos_t pos) const = 0; - virtual void update_length (samplecnt_t cnt) = 0; + timecnt_t length() const; + + virtual bool empty () const; + virtual samplecnt_t length_samples (timepos_t const & pos) const { return _length.samples(); }; + virtual void update_length (timecnt_t const & cnt) {} void set_take_id (std::string id) { _take_id =id; } const std::string& take_id () const { return _take_id; } @@ -114,14 +116,15 @@ public: CueMarkers const & cue_markers() const { return _cue_markers; } bool add_cue_marker (CueMarker const &); - bool move_cue_marker (CueMarker const &, samplepos_t source_relative_position); + bool move_cue_marker (CueMarker const &, timepos_t const & source_relative_position); bool remove_cue_marker (CueMarker const &); bool rename_cue_marker (CueMarker&, std::string const &); bool clear_cue_markers (); PBD::Signal0 CueMarkersChanged; - virtual samplepos_t natural_position() const { return _natural_position; } - virtual void set_natural_position (samplepos_t pos); + virtual timepos_t natural_position() const { return _natural_position; } + virtual void set_natural_position (timepos_t const & pos); + bool have_natural_position() const { return _have_natural_position; } void set_allow_remove_if_empty (bool yn); @@ -143,19 +146,19 @@ public: std::string captured_for() const { return _captured_for; } protected: - DataType _type; - Flag _flags; - time_t _timestamp; - std::string _take_id; - samplepos_t _natural_position; - samplepos_t _have_natural_position; - bool _analysed; + DataType _type; + Flag _flags; + time_t _timestamp; + std::string _take_id; + timepos_t _natural_position; + bool _have_natural_position; + bool _analysed; GATOMIC_QUAL gint _use_count; /* atomic */ - uint32_t _level; /* how deeply nested is this source w.r.t a disk file */ - std::string _ancestor_name; - std::string _captured_for; - XrunPositions _xruns; - CueMarkers _cue_markers; + uint32_t _level; /* how deeply nested is this source w.r.t a disk file */ + std::string _ancestor_name; + std::string _captured_for; + timecnt_t _length; + XrunPositions _xruns; mutable Glib::Threads::Mutex _lock; mutable Glib::Threads::Mutex _analysis_lock; diff --git a/libs/ardour/ardour/source_factory.h b/libs/ardour/ardour/source_factory.h index 21a2d8a988..77dc774cf3 100644 --- a/libs/ardour/ardour/source_factory.h +++ b/libs/ardour/ardour/source_factory.h @@ -62,7 +62,7 @@ class LIBARDOUR_API SourceFactory { static boost::shared_ptr createFromPlaylist (DataType type, Session& s, boost::shared_ptr p, const PBD::ID& orig, const std::string& name, - uint32_t chn, sampleoffset_t start, samplecnt_t len, bool copy, bool defer_peaks); + uint32_t chn, timepos_t start, timepos_t const & len, bool copy, bool defer_peaks); static Glib::Threads::Cond PeaksToBuild; static Glib::Threads::Mutex peak_building_lock; diff --git a/libs/ardour/ardour/srcfilesource.h b/libs/ardour/ardour/srcfilesource.h index c110ac634a..b7fa928b82 100644 --- a/libs/ardour/ardour/srcfilesource.h +++ b/libs/ardour/ardour/srcfilesource.h @@ -42,9 +42,9 @@ public: float sample_rate () const { return _session.nominal_sample_rate(); } - samplepos_t natural_position() const { return _source->natural_position() * _ratio;} - samplecnt_t readable_length() const { return _source->readable_length() * _ratio; } - samplecnt_t length (samplepos_t pos) const { return _source->length(pos) * _ratio; } + timepos_t natural_position() const { return _source->natural_position() * _ratio;} + samplecnt_t readable_length_samples() const { return _source->length_samples (timepos_t (Temporal::AudioTime)) * _ratio; } + samplecnt_t length (samplepos_t /*pos*/) const { return _source->length_samples (timepos_t (Temporal::AudioTime)) * _ratio; } bool can_be_analysed() const { return false; } bool clamped_at_unity() const { return false; } diff --git a/libs/ardour/ardour/tempo.h b/libs/ardour/ardour/tempo.h index 62c1971979..8caad9a5eb 100644 --- a/libs/ardour/ardour/tempo.h +++ b/libs/ardour/ardour/tempo.h @@ -50,6 +50,11 @@ class XMLNode; namespace ARDOUR { +enum PositionLockStyle { + AudioTime, + MusicTime +}; + class Meter; class TempoMap; diff --git a/libs/ardour/ardour/timefx_request.h b/libs/ardour/ardour/timefx_request.h index 29f175534f..96bd27ad05 100644 --- a/libs/ardour/ardour/timefx_request.h +++ b/libs/ardour/ardour/timefx_request.h @@ -19,15 +19,21 @@ #ifndef __libardour_timefx_request_h__ #define __libardour_timefx_request_h__ +#include "temporal/types.h" #include "ardour/interthread_info.h" namespace ARDOUR { struct TimeFXRequest : public InterThreadInfo { TimeFXRequest() - : time_fraction(0), pitch_fraction(0), - use_soundtouch(false), quick_seek(false), antialias(false), opts(0) {} - float time_fraction; + : time_fraction(0,0) + , pitch_fraction(0) + , use_soundtouch(false) + , quick_seek(false) + , antialias(false) + , opts(0) {} + + Temporal::ratio_t time_fraction; float pitch_fraction; /* SoundTouch */ bool use_soundtouch; diff --git a/libs/ardour/ardour/transient_detector.h b/libs/ardour/ardour/transient_detector.h index 4c5b047db1..129181dab5 100644 --- a/libs/ardour/ardour/transient_detector.h +++ b/libs/ardour/ardour/transient_detector.h @@ -25,7 +25,7 @@ namespace ARDOUR { class AudioSource; -class Readable; +class AudioReadable; class Session; class LIBARDOUR_API TransientDetector : public AudioAnalyser @@ -39,8 +39,8 @@ public: void set_threshold (float); void set_sensitivity (uint32_t, float); - int run (const std::string& path, Readable*, uint32_t channel, AnalysisFeatureList& results); - void update_positions (Readable* src, uint32_t channel, AnalysisFeatureList& results); + int run (const std::string& path, AudioReadable*, uint32_t channel, AnalysisFeatureList& results); + void update_positions (AudioReadable* src, uint32_t channel, AnalysisFeatureList& results); static void cleanup_transients (AnalysisFeatureList&, float sr, float gap_msecs); diff --git a/libs/ardour/ardour/types.h b/libs/ardour/ardour/types.h index f46d80639b..5dd927cf03 100644 --- a/libs/ardour/ardour/types.h +++ b/libs/ardour/ardour/types.h @@ -43,6 +43,7 @@ #include #include "temporal/bbt_time.h" +#include "temporal/range.h" #include "temporal/superclock.h" #include "temporal/time.h" #include "temporal/timeline.h" @@ -51,8 +52,6 @@ #include "pbd/id.h" #include "pbd/microseconds.h" -#include "evoral/Range.h" - #include "ardour/chan_count.h" #include "ardour/plugin_types.h" @@ -355,64 +354,41 @@ struct MusicSample { MusicSample operator- (MusicSample other) { return MusicSample (sample - other.sample, 0); } }; -/* XXX: slightly unfortunate that there is this and Evoral::Range<>, - but this has a uint32_t id which Evoral::Range<> does not. -*/ -struct AudioRange { - samplepos_t start; - samplepos_t end; +/* Just a Temporal::Range with an ID for identity + */ +struct TimelineRange : public Temporal::TimeRange +{ uint32_t id; - AudioRange (samplepos_t s, samplepos_t e, uint32_t i) : start (s), end (e) , id (i) {} + TimelineRange (Temporal::timepos_t const & s, Temporal::timepos_t e, uint32_t i) : Temporal::TimeRange (s, e), id (i) {} - samplecnt_t length() const { return end - start + 1; } + samplecnt_t length_samples() const { return length().samples(); } - bool operator== (const AudioRange& other) const { - return start == other.start && end == other.end && id == other.id; + bool operator== (const TimelineRange& other) const { + return id == other.id && Temporal::TimeRange::operator== (other); } - bool equal (const AudioRange& other) const { - return start == other.start && end == other.end; - } - - Evoral::OverlapType coverage (samplepos_t s, samplepos_t e) const { - return Evoral::coverage (start, end, s, e); - } -}; - -struct MusicRange { - Temporal::BBT_Time start; - Temporal::BBT_Time end; - uint32_t id; - - MusicRange (Temporal::BBT_Time& s, Temporal::BBT_Time& e, uint32_t i) - : start (s), end (e), id (i) {} - - bool operator== (const MusicRange& other) const { - return start == other.start && end == other.end && id == other.id; - } - - bool equal (const MusicRange& other) const { - return start == other.start && end == other.end; + bool equal (const TimelineRange& other) const { + return Temporal::TimeRange::operator== (other); } }; class CueMarker { public: - CueMarker (std::string const& text, samplepos_t position) : _text (text), _position (position) {} + CueMarker (std::string const& text, timepos_t const & position) : _text (text), _position (position) {} std::string text() const { return _text; } void set_text (std::string const & str) { _text = str; } - samplepos_t position() const { return _position; } - void set_position (samplepos_t pos) { _position = pos; } + timepos_t position() const { return _position; } + void set_position (timepos_t const & pos) { _position = pos; } bool operator== (CueMarker const & other) const { return _position == other.position() && _text == other.text(); } bool operator< (CueMarker const & other) const { return _position < other.position(); } private: std::string _text; - samplepos_t _position; + timepos_t _position; }; typedef std::set CueMarkers; @@ -692,11 +668,6 @@ struct CleanupReport { size_t space; }; -enum PositionLockStyle { - AudioTime, - MusicTime -}; - /** A struct used to describe changes to processors in a route. * This is useful because objects that respond to a change in processors * can optimise what work they do based on details of what has changed. diff --git a/libs/ardour/ardour/types_convert.h b/libs/ardour/ardour/types_convert.h index 98f543cce0..9a4192d8b9 100644 --- a/libs/ardour/ardour/types_convert.h +++ b/libs/ardour/ardour/types_convert.h @@ -51,7 +51,6 @@ DEFINE_ENUM_CONVERT(ARDOUR::SyncSource) DEFINE_ENUM_CONVERT(ARDOUR::ShuttleUnits) DEFINE_ENUM_CONVERT(ARDOUR::ClockDeltaMode) DEFINE_ENUM_CONVERT(ARDOUR::DenormalModel) -DEFINE_ENUM_CONVERT(ARDOUR::PositionLockStyle) DEFINE_ENUM_CONVERT(ARDOUR::FadeShape) DEFINE_ENUM_CONVERT(ARDOUR::RegionSelectionAfterSplit) DEFINE_ENUM_CONVERT(ARDOUR::RangeSelectionAfterSplit) @@ -88,7 +87,7 @@ inline std::string to_string (ARDOUR::timepos_t val) template <> inline ARDOUR::timepos_t string_to (std::string const & str) { - ARDOUR::timepos_t tmp; + ARDOUR::timepos_t tmp (Temporal::AudioTime); /* domain may be changed */ tmp.string_to (str); return tmp; } @@ -116,7 +115,7 @@ inline std::string to_string (ARDOUR::timecnt_t val) template <> inline ARDOUR::timecnt_t string_to (std::string const & str) { - ARDOUR::timecnt_t tmp; + ARDOUR::timecnt_t tmp (Temporal::AudioTime); /* domain may change */ tmp.string_to (str); return tmp; } diff --git a/libs/ardour/audio_playlist.cc b/libs/ardour/audio_playlist.cc index ee0f3d1c07..70b26a6fc2 100644 --- a/libs/ardour/audio_playlist.cc +++ b/libs/ardour/audio_playlist.cc @@ -67,13 +67,14 @@ AudioPlaylist::AudioPlaylist (boost::shared_ptr other, stri { } -AudioPlaylist::AudioPlaylist (boost::shared_ptr other, samplepos_t start, samplecnt_t cnt, string name, bool hidden) +AudioPlaylist::AudioPlaylist (boost::shared_ptr other, timepos_t const & start, timepos_t const & cnt, string name, bool hidden) : Playlist (other, start, cnt, name, hidden) { RegionReadLock rlock2 (const_cast (other.get())); in_set_state++; - samplepos_t const end = start + cnt - 1; + const timepos_t tend = start + cnt; + samplepos_t end = tend.samples(); /* Audio regions that have been created by the Playlist constructor will currently have the same fade in/out as the regions that they @@ -89,43 +90,46 @@ AudioPlaylist::AudioPlaylist (boost::shared_ptr other, samp samplecnt_t fade_in = 64; samplecnt_t fade_out = 64; - switch (region->coverage (start, end)) { - case Evoral::OverlapNone: + switch (region->coverage (start, tend)) { + case Temporal::OverlapNone: continue; - case Evoral::OverlapInternal: + case Temporal::OverlapInternal: { - samplecnt_t const offset = start - region->position (); + samplecnt_t const offset = start.samples() - region->position_sample (); samplecnt_t const trim = region->last_sample() - end; if (region->fade_in()->back()->when > offset) { - fade_in = region->fade_in()->back()->when - offset; + fade_in = region->fade_in()->back()->when.earlier (timepos_t (offset)).samples(); } if (region->fade_out()->back()->when > trim) { - fade_out = region->fade_out()->back()->when - trim; + fade_out = region->fade_out()->back()->when.earlier (timepos_t (trim)).samples(); } break; } - case Evoral::OverlapStart: { - if (end > region->position() + region->fade_in()->back()->when) - fade_in = region->fade_in()->back()->when; //end is after fade-in, preserve the fade-in - if (end > region->last_sample() - region->fade_out()->back()->when) - fade_out = region->fade_out()->back()->when - ( region->last_sample() - end ); //end is inside the fadeout, preserve the fades endpoint + case Temporal::OverlapStart: { + if (timepos_t (end) > region->nt_position() + region->fade_in()->back()->when) { + fade_in = region->fade_in()->back()->when.samples(); //end is after fade-in, preserve the fade-in + } + if (timepos_t (end) >= region->nt_end().earlier (region->fade_out()->back()->when)) { + fade_out = region->fade_out()->back()->when.earlier (timepos_t (region->last_sample() - end)).samples(); //end is inside the fadeout, preserve the fades endpoint + } break; } - case Evoral::OverlapEnd: { - if (start < region->last_sample() - region->fade_out()->back()->when) //start is before fade-out, preserve the fadeout - fade_out = region->fade_out()->back()->when; - - if (start < region->position() + region->fade_in()->back()->when) - fade_in = region->fade_in()->back()->when - (start - region->position()); //end is inside the fade-in, preserve the fade-in endpoint + case Temporal::OverlapEnd: { + if (start < region->nt_end().earlier (region->fade_out()->back()->when)) { //start is before fade-out, preserve the fadeout + fade_out = region->fade_out()->back()->when.samples(); + } + if (start < region->nt_position() + region->fade_in()->back()->when) { + fade_in = region->fade_in()->back()->when.earlier (start.distance (region->nt_position())).samples(); //end is inside the fade-in, preserve the fade-in endpoint + } break; } - case Evoral::OverlapExternal: - fade_in = region->fade_in()->back()->when; - fade_out = region->fade_out()->back()->when; + case Temporal::OverlapExternal: + fade_in = region->fade_in()->back()->when.samples(); + fade_out = region->fade_out()->back()->when.samples(); break; } @@ -149,23 +153,23 @@ struct ReadSorter { return a->layer() > b->layer(); } - return a->position() < b->position(); + return a->nt_position() < b->nt_position(); } }; /** A segment of region that needs to be read */ struct Segment { - Segment (boost::shared_ptr r, Evoral::Range a) : region (r), range (a) {} + Segment (boost::shared_ptr r, Temporal::Range a) : region (r), range (a) {} boost::shared_ptr region; ///< the region - Evoral::Range range; ///< range of the region to read, in session samples + Temporal::Range range; ///< range of the region to read, in session samples }; /** @param start Start position in session samples. * @param cnt Number of samples to read. */ -ARDOUR::samplecnt_t -AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, samplepos_t start, samplecnt_t cnt, unsigned chan_n) +ARDOUR::timecnt_t +AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, timepos_t const & start, timecnt_t const & cnt, uint32_t chan_n) { DEBUG_TRACE (DEBUG::AudioPlayback, string_compose ("Playlist %1 read @ %2 for %3, channel %4, regions %5 mixdown @ %6 gain @ %7\n", name(), start, cnt, chan_n, regions.size(), mixdown_buffer, gain_buffer)); @@ -183,7 +187,7 @@ AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, sa zeroed. */ - memset (buf, 0, sizeof (Sample) * cnt); + memset (buf, 0, sizeof (Sample) * cnt.samples()); /* this function is never called from a realtime thread, so its OK to block (for short intervals). @@ -194,14 +198,14 @@ AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, sa /* Find all the regions that are involved in the bit we are reading, and sort them by descending layer and ascending position. */ - boost::shared_ptr all = regions_touched_locked (start, start + cnt - 1); + boost::shared_ptr all = regions_touched_locked (start, start + cnt); all->sort (ReadSorter ()); /* This will be a list of the bits of our read range that we have handled completely (ie for which no more regions need to be read). It is a list of ranges in session samples. */ - Evoral::RangeList done; + Temporal::RangeList done; /* This will be a list of the bits of regions that we need to read */ list to_do; @@ -224,30 +228,31 @@ AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, sa /* Work out which bits of this region need to be read; first, trim to the range we are reading... */ - Evoral::Range region_range = ar->range (); - region_range.from = max (region_range.from, start); - region_range.to = min (region_range.to, start + cnt - 1); + Temporal::Range rrange = ar->range_samples (); + Temporal::Range region_range (max (rrange.start(), start), + min (rrange.end(), start + cnt)); /* ... and then remove the bits that are already done */ - Evoral::RangeList region_to_do = Evoral::subtract (region_range, done); + Temporal::RangeList region_to_do = region_range.subtract (done); /* Make a note to read those bits, adding their bodies (the parts between end-of-fade-in and start-of-fade-out) to the `done' list. */ - Evoral::RangeList::List t = region_to_do.get (); + Temporal::RangeList::List t = region_to_do.get (); - for (Evoral::RangeList::List::iterator j = t.begin(); j != t.end(); ++j) { - Evoral::Range d = *j; + for (Temporal::RangeList::List::iterator j = t.begin(); j != t.end(); ++j) { + Temporal::Range d = *j; to_do.push_back (Segment (ar, d)); if (ar->opaque ()) { /* Cut this range down to just the body and mark it done */ - Evoral::Range body = ar->body_range (); - if (body.from < d.to && body.to > d.from) { - d.from = max (d.from, body.from); - d.to = min (d.to, body.to); + Temporal::Range body = ar->body_range (); + + if (body.start() < d.end() && body.end() > d.start()) { + d.set_start (max (d.start(), body.start())); + d.set_end (min (d.end(), body.end())); done.add (d); } } @@ -255,12 +260,14 @@ AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, sa } /* Now go backwards through the to_do list doing the actual reads */ + for (list::reverse_iterator i = to_do.rbegin(); i != to_do.rend(); ++i) { DEBUG_TRACE (DEBUG::AudioPlayback, string_compose ("\tPlaylist %1 read %2 @ %3 for %4, channel %5, buf @ %6 offset %7\n", - name(), i->region->name(), i->range.from, - i->range.to - i->range.from + 1, (int) chan_n, - buf, i->range.from - start)); - i->region->read_at (buf + i->range.from - start, mixdown_buffer, gain_buffer, i->range.from, i->range.to - i->range.from + 1, chan_n); + name(), i->region->name(), i->range.start(), + i->range.length(), (int) chan_n, + buf, i->range.start().earlier (start))); + + i->region->read_at (buf + start.distance (i->range.start()).samples(), mixdown_buffer, gain_buffer, i->range.start().samples(), i->range.start().distance (i->range.end()).samples(), chan_n); } return cnt; @@ -278,9 +285,9 @@ AudioPlaylist::dump () const for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) { r = *i; cerr << " " << r->name() << " @ " << r << " [" - << r->start() << "+" << r->length() + << r->nt_start() << "+" << r->nt_length() << "] at " - << r->position() + << r->nt_position() << " on layer " << r->layer () << endl; @@ -460,7 +467,7 @@ AudioPlaylist::pre_uncombine (vector >& originals, boo original region. */ - if (cr->fade_in()->back()->when <= ar->length()) { + if (cr->fade_in()->back()->when <= ar->nt_length()) { /* don't do this if the fade is longer than the * region */ @@ -474,7 +481,7 @@ AudioPlaylist::pre_uncombine (vector >& originals, boo original region. */ - if (cr->fade_out()->back()->when <= ar->length()) { + if (cr->fade_out()->back()->when <= ar->nt_length()) { /* don't do this if the fade is longer than the * region */ diff --git a/libs/ardour/audio_playlist_source.cc b/libs/ardour/audio_playlist_source.cc index 0796f77e80..d0bcf74f2b 100644 --- a/libs/ardour/audio_playlist_source.cc +++ b/libs/ardour/audio_playlist_source.cc @@ -45,13 +45,14 @@ using namespace ARDOUR; using namespace PBD; AudioPlaylistSource::AudioPlaylistSource (Session& s, const ID& orig, const std::string& name, boost::shared_ptr p, - uint32_t chn, sampleoffset_t begin, samplecnt_t len, Source::Flag flags) + uint32_t chn, timepos_t const & begin, timepos_t const & len, Source::Flag flags) : Source (s, DataType::AUDIO, name) , PlaylistSource (s, orig, name, p, DataType::AUDIO, begin, len, flags) , AudioSource (s, name) , _playlist_channel (chn) { - AudioSource::_length = len; + AudioSource::_length = timecnt_t (len); + ensure_buffers_for_level (_level, _session.sample_rate()); } AudioPlaylistSource::AudioPlaylistSource (Session& s, const XMLNode& node) @@ -70,7 +71,7 @@ AudioPlaylistSource::AudioPlaylistSource (Session& s, const XMLNode& node) throw failed_constructor (); } - AudioSource::_length = _playlist_length; + _length = timecnt_t (_playlist_length); } AudioPlaylistSource::~AudioPlaylistSource () @@ -108,9 +109,9 @@ AudioPlaylistSource::set_state (const XMLNode& node, int version, bool with_desc } } - pair extent = _playlist->get_extent(); + pair extent = _playlist->get_extent(); - AudioSource::_length = extent.second - extent.first; + AudioSource::_length = extent.first.distance (extent.second); if (!node.get_property (X_("channel"), _playlist_channel)) { throw failed_constructor (); @@ -130,8 +131,8 @@ AudioPlaylistSource::read_unlocked (Sample* dst, samplepos_t start, samplecnt_t * is not supposed be part of our data. */ - if (cnt > _playlist_length - start) { - to_read = _playlist_length - start; + if (cnt > _playlist_length.samples() - start) { + to_read = _playlist_length.samples() - start; to_zero = cnt - to_read; } else { to_read = cnt; @@ -141,7 +142,7 @@ AudioPlaylistSource::read_unlocked (Sample* dst, samplepos_t start, samplecnt_t boost::scoped_array sbuf(new float[to_read]); boost::scoped_array gbuf(new gain_t[to_read]); - boost::dynamic_pointer_cast(_playlist)->read (dst, sbuf.get(), gbuf.get(), start+_playlist_offset, to_read, _playlist_channel); + boost::dynamic_pointer_cast(_playlist)->read (dst, sbuf.get(), gbuf.get(), timepos_t (start)+_playlist_offset, timecnt_t (to_read), _playlist_channel); if (to_zero) { memset (dst+to_read, 0, sizeof (Sample) * to_zero); diff --git a/libs/ardour/audio_region_importer.cc b/libs/ardour/audio_region_importer.cc index 94a30527e8..5becea523b 100644 --- a/libs/ardour/audio_region_importer.cc +++ b/libs/ardour/audio_region_importer.cc @@ -314,7 +314,7 @@ AudioRegionImporter::prepare_region () // create region and update XML boost::shared_ptr r = RegionFactory::create (source_list, xml_region); if (session.config.get_glue_new_regions_to_bars_and_beats ()) { - r->set_position_lock_style (MusicTime); + r->set_position_time_domain (Temporal::BeatTime); } region.push_back (r); if (*region.begin()) { diff --git a/libs/ardour/audio_track.cc b/libs/ardour/audio_track.cc index d262bef1de..b121e1a9b8 100644 --- a/libs/ardour/audio_track.cc +++ b/libs/ardour/audio_track.cc @@ -213,7 +213,7 @@ AudioTrack::export_stuff (BufferSet& buffers, samplepos_t start, samplecnt_t nfr assert(buffers.count().n_audio() >= 1); assert ((samplecnt_t) buffers.get_audio(0).capacity() >= nframes); - if (apl->read (buffers.get_audio(0).data(), mix_buffer.get(), gain_buffer.get(), start, nframes) != nframes) { + if (apl->read (buffers.get_audio(0).data(), mix_buffer.get(), gain_buffer.get(), timepos_t (start), timecnt_t (nframes)) != nframes) { return -1; } @@ -223,7 +223,7 @@ AudioTrack::export_stuff (BufferSet& buffers, samplepos_t start, samplecnt_t nfr ++bi; for ( ; bi != buffers.audio_end(); ++bi, ++n) { if (n < _disk_reader->output_streams().n_audio()) { - if (apl->read (bi->data(), mix_buffer.get(), gain_buffer.get(), start, nframes, n) != nframes) { + if (apl->read (bi->data(), mix_buffer.get(), gain_buffer.get(), timepos_t (start), timecnt_t (nframes), n) != nframes) { return -1; } b = bi->data(); @@ -402,14 +402,15 @@ AudioTrack::freeze_me (InterThreadInfo& itt) PropertyList plist; plist.add (Properties::start, 0); - plist.add (Properties::length, srcs[0]->length(srcs[0]->natural_position())); + plist.add (Properties::length, srcs[0]->length()); plist.add (Properties::name, region_name); plist.add (Properties::whole_file, true); boost::shared_ptr region (RegionFactory::create (srcs, plist, false)); new_playlist->set_orig_track_id (id()); - new_playlist->add_region (region, _session.current_start_sample()); +#warning NUTEMPO fixme this probably should not use samples unconditionally + new_playlist->add_region (region, timepos_t (_session.current_start_sample())); new_playlist->set_frozen (true); region->set_locked (true); diff --git a/libs/ardour/audioanalyser.cc b/libs/ardour/audioanalyser.cc index bccd6c3e06..fa91284a0d 100644 --- a/libs/ardour/audioanalyser.cc +++ b/libs/ardour/audioanalyser.cc @@ -102,14 +102,14 @@ AudioAnalyser::reset () } int -AudioAnalyser::analyse (const string& path, Readable* src, uint32_t channel) +AudioAnalyser::analyse (const string& path, AudioReadable* src, uint32_t channel) { stringstream outss; Plugin::FeatureSet features; int ret = -1; bool done = false; Sample* data = 0; - samplecnt_t len = src->readable_length(); + samplecnt_t len = src->readable_length_samples(); samplepos_t pos = 0; float* bufs[1] = { 0 }; diff --git a/libs/ardour/audioregion.cc b/libs/ardour/audioregion.cc index 619ca7e0b5..7efe67895d 100644 --- a/libs/ardour/audioregion.cc +++ b/libs/ardour/audioregion.cc @@ -85,10 +85,13 @@ namespace ARDOUR { static void reverse_curve (boost::shared_ptr dst, boost::shared_ptr src) { - size_t len = src->when(false); + const timepos_t end = src->when(false); // TODO read-lock of src (!) for (Evoral::ControlList::const_reverse_iterator it = src->rbegin(); it!=src->rend(); it++) { - dst->fast_simple_add (len - (*it)->when, (*it)->value); + /* ugh ... the double "distance" calls (with totally different + semantics ... horrible + */ + dst->fast_simple_add (timepos_t ((*it)->when.distance (end)), (*it)->value); } } @@ -108,17 +111,17 @@ static void generate_db_fade (boost::shared_ptr dst, double len, int num_steps, float dB_drop) { dst->clear (); - dst->fast_simple_add (0, 1); + dst->fast_simple_add (timepos_t (Temporal::AudioTime), 1); //generate a fade-out curve by successively applying a gain drop float fade_speed = dB_to_coefficient(dB_drop / (float) num_steps); float coeff = GAIN_COEFF_UNITY; for (int i = 1; i < (num_steps-1); i++) { coeff *= fade_speed; - dst->fast_simple_add (len*(double)i/(double)num_steps, coeff); + dst->fast_simple_add (timepos_t (len*(double)i/(double)num_steps), coeff); } - dst->fast_simple_add (len, GAIN_COEFF_SMALL); + dst->fast_simple_add (timepos_t (len), GAIN_COEFF_SMALL); } static void @@ -194,6 +197,7 @@ AudioRegion::register_properties () add_property (_envelope); } +#warning NUTEMPO QUESTION what time domains should be used here? #define AUDIOREGION_STATE_DEFAULT \ _envelope_active (Properties::envelope_active, false) \ , _default_fade_in (Properties::default_fade_in, true) \ @@ -201,10 +205,10 @@ AudioRegion::register_properties () , _fade_in_active (Properties::fade_in_active, true) \ , _fade_out_active (Properties::fade_out_active, true) \ , _scale_amplitude (Properties::scale_amplitude, 1.0) \ - , _fade_in (Properties::fade_in, boost::shared_ptr (new AutomationList (Evoral::Parameter (FadeInAutomation)))) \ - , _inverse_fade_in (Properties::inverse_fade_in, boost::shared_ptr (new AutomationList (Evoral::Parameter (FadeInAutomation)))) \ - , _fade_out (Properties::fade_out, boost::shared_ptr (new AutomationList (Evoral::Parameter (FadeOutAutomation)))) \ - , _inverse_fade_out (Properties::inverse_fade_out, boost::shared_ptr (new AutomationList (Evoral::Parameter (FadeOutAutomation)))) + , _fade_in (Properties::fade_in, boost::shared_ptr (new AutomationList (Evoral::Parameter (FadeInAutomation), Temporal::AudioTime))) \ + , _inverse_fade_in (Properties::inverse_fade_in, boost::shared_ptr (new AutomationList (Evoral::Parameter (FadeInAutomation), Temporal::AudioTime))) \ + , _fade_out (Properties::fade_out, boost::shared_ptr (new AutomationList (Evoral::Parameter (FadeOutAutomation), Temporal::AudioTime))) \ + , _inverse_fade_out (Properties::inverse_fade_out, boost::shared_ptr (new AutomationList (Evoral::Parameter (FadeOutAutomation), Temporal::AudioTime))) #define AUDIOREGION_COPY_STATE(other) \ _envelope_active (Properties::envelope_active, other->_envelope_active) \ @@ -238,7 +242,7 @@ AudioRegion::init () AudioRegion::AudioRegion (Session& s, timecnt_t const & start, timecnt_t const & len, std::string name) : Region (s, start, len, name, DataType::AUDIO) , AUDIOREGION_STATE_DEFAULT - , _envelope (Properties::envelope, boost::shared_ptr (new AutomationList (Evoral::Parameter(EnvelopeAutomation)))) + , _envelope (Properties::envelope, boost::shared_ptr (new AutomationList (Evoral::Parameter(EnvelopeAutomation), Temporal::AudioTime))) , _automatable (s) , _fade_in_suspended (0) , _fade_out_suspended (0) @@ -251,7 +255,7 @@ AudioRegion::AudioRegion (Session& s, timecnt_t const & start, timecnt_t const AudioRegion::AudioRegion (const SourceList& srcs) : Region (srcs) , AUDIOREGION_STATE_DEFAULT - , _envelope (Properties::envelope, boost::shared_ptr (new AutomationList (Evoral::Parameter(EnvelopeAutomation)))) + , _envelope (Properties::envelope, boost::shared_ptr (new AutomationList (Evoral::Parameter(EnvelopeAutomation), Temporal::AudioTime))) , _automatable(srcs[0]->session()) , _fade_in_suspended (0) , _fade_out_suspended (0) @@ -266,7 +270,7 @@ AudioRegion::AudioRegion (boost::shared_ptr other) /* As far as I can see, the _envelope's times are relative to region position, and have nothing * to do with sources (and hence _start). So when we copy the envelope, we just use the supplied offset. */ - , _envelope (Properties::envelope, boost::shared_ptr (new AutomationList (*other->_envelope.val(), 0, other->_length))) + , _envelope (Properties::envelope, boost::shared_ptr (new AutomationList (*other->_envelope.val(), timepos_t (Temporal::AudioTime), timepos_t (other->_length)))) , _automatable (other->session()) , _fade_in_suspended (0) , _fade_out_suspended (0) @@ -288,7 +292,7 @@ AudioRegion::AudioRegion (boost::shared_ptr other, timecnt_t /* As far as I can see, the _envelope's times are relative to region position, and have nothing to do with sources (and hence _start). So when we copy the envelope, we just use the supplied offset. */ - , _envelope (Properties::envelope, boost::shared_ptr (new AutomationList (*other->_envelope.val(), offset.sample, other->_length))) + , _envelope (Properties::envelope, boost::shared_ptr (new AutomationList (*other->_envelope.val(), timepos_t (offset.samples()), timepos_t (other->_length)))) , _automatable (other->session()) , _fade_in_suspended (0) , _fade_out_suspended (0) @@ -326,7 +330,7 @@ AudioRegion::AudioRegion (boost::shared_ptr other, const Sour AudioRegion::AudioRegion (SourceList& srcs) : Region (srcs) , AUDIOREGION_STATE_DEFAULT - , _envelope (Properties::envelope, boost::shared_ptr (new AutomationList(Evoral::Parameter(EnvelopeAutomation)))) + , _envelope (Properties::envelope, boost::shared_ptr (new AutomationList(Evoral::Parameter(EnvelopeAutomation), Temporal::AudioTime))) , _automatable(srcs[0]->session()) , _fade_in_suspended (0) , _fade_out_suspended (0) @@ -368,7 +372,7 @@ AudioRegion::post_set (const PropertyChange& /*ignored*/) } /* If _length changed, adjust our gain envelope accordingly */ - _envelope->truncate_end (_length); + _envelope->truncate_end (timepos_t (_length.val())); } void @@ -454,7 +458,7 @@ samplecnt_t AudioRegion::read (Sample* buf, samplepos_t pos, samplecnt_t cnt, int channel) const { /* raw read, no fades, no gain, nada */ - return read_from_sources (_sources, _length, buf, _position + pos, cnt, channel); + return read_from_sources (_sources, _length.val().samples(), buf, _position.val().samples() + pos, cnt, channel); } samplecnt_t @@ -464,10 +468,7 @@ AudioRegion::master_read_at (Sample *buf, Sample* /*mixdown_buffer*/, float* /*g /* do not read gain/scaling/fades and do not count this disk i/o in statistics */ assert (cnt >= 0); - return read_from_sources ( - _master_sources, _master_sources.front()->length (_master_sources.front()->natural_position()), - buf, position, cnt, chan_n - ); + return read_from_sources (_master_sources, _master_sources.front()->length ().samples(), buf, position, cnt, chan_n); } /** @param buf Buffer to mix data into. @@ -500,15 +501,17 @@ AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, /* WORK OUT WHERE TO GET DATA FROM */ samplecnt_t to_read; + const samplepos_t psamples = _position.val().samples(); + const samplecnt_t lsamples = _length.val().samples(); - assert (position >= _position); - sampleoffset_t const internal_offset = position - _position; + assert (position >= psamples); + sampleoffset_t const internal_offset = position - psamples; - if (internal_offset >= _length) { + if (internal_offset >= lsamples) { return 0; /* read nothing */ } - if ((to_read = min (cnt, _length - internal_offset)) == 0) { + if ((to_read = min (cnt, lsamples - internal_offset)) == 0) { return 0; /* read nothing */ } @@ -516,7 +519,7 @@ AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, if (!pl){ return 0; } - + /* COMPUTE DETAILS OF ANY FADES INVOLVED IN THIS READ */ /* Amount (length) of fade in that we are dealing with in this read */ @@ -536,7 +539,7 @@ AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, if (_fade_in_active && _session.config.get_use_region_fades()) { - samplecnt_t fade_in_length = (samplecnt_t) _fade_in->when(false); + samplecnt_t fade_in_length = _fade_in->when(false).samples(); /* see if this read is within the fade in */ @@ -568,8 +571,8 @@ AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, * */ - fade_interval_start = max (internal_offset, _length - samplecnt_t (_fade_out->when(false))); - samplecnt_t fade_interval_end = min(internal_offset + to_read, _length.val()); + fade_interval_start = max (internal_offset, lsamples - _fade_out->when(false).samples()); + samplecnt_t fade_interval_end = min(internal_offset + to_read, lsamples); if (fade_interval_end > fade_interval_start) { /* (part of the) the fade out is in this buffer */ @@ -584,14 +587,14 @@ AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, may need to mix with the existing data. */ - if (read_from_sources (_sources, _length, mixdown_buffer, position, to_read, chan_n) != to_read) { + if (read_from_sources (_sources, lsamples, mixdown_buffer, psamples, to_read, chan_n) != to_read) { return 0; } /* APPLY REGULAR GAIN CURVES AND SCALING TO mixdown_buffer */ if (envelope_active()) { - _envelope->curve().get_vector (internal_offset, internal_offset + to_read, gain_buffer, to_read); + _envelope->curve().get_vector (timepos_t (internal_offset), timepos_t (internal_offset + to_read), gain_buffer, to_read); if (_scale_amplitude != 1.0f) { for (samplecnt_t n = 0; n < to_read; ++n) { @@ -612,7 +615,7 @@ AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, * "buf" contains data from lower regions already. So this operation * fades out the existing material. */ - + bool is_opaque = opaque(); if (fade_in_limit != 0) { @@ -624,7 +627,7 @@ AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, * power), so we have to fetch it. */ - _inverse_fade_in->curve().get_vector (internal_offset, internal_offset + fade_in_limit, gain_buffer, fade_in_limit); + _inverse_fade_in->curve().get_vector (timepos_t (internal_offset), timepos_t (internal_offset + fade_in_limit), gain_buffer, fade_in_limit); /* Fade the data from lower layers out */ for (samplecnt_t n = 0; n < fade_in_limit; ++n) { @@ -633,7 +636,7 @@ AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, /* refill gain buffer with the fade in */ - _fade_in->curve().get_vector (internal_offset, internal_offset + fade_in_limit, gain_buffer, fade_in_limit); + _fade_in->curve().get_vector (timepos_t (internal_offset), timepos_t (internal_offset + fade_in_limit), gain_buffer, fade_in_limit); } else { @@ -641,14 +644,14 @@ AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, * in) for the fade out of lower layers */ - _fade_in->curve().get_vector (internal_offset, internal_offset + fade_in_limit, gain_buffer, fade_in_limit); + _fade_in->curve().get_vector (timepos_t (internal_offset), timepos_t (internal_offset + fade_in_limit), gain_buffer, fade_in_limit); for (samplecnt_t n = 0; n < fade_in_limit; ++n) { buf[n] *= 1 - gain_buffer[n]; } } } else { - _fade_in->curve().get_vector (internal_offset, internal_offset + fade_in_limit, gain_buffer, fade_in_limit); + _fade_in->curve().get_vector (timepos_t (internal_offset), timepos_t (internal_offset + fade_in_limit), gain_buffer, fade_in_limit); } /* Mix our newly-read data in, with the fade */ @@ -659,12 +662,12 @@ AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, if (fade_out_limit != 0) { - samplecnt_t const curve_offset = fade_interval_start - (_length - _fade_out->when(false)); + samplecnt_t const curve_offset = fade_interval_start - _fade_out->when(false).distance (timepos_t (_length)).samples(); if (is_opaque) { if (_inverse_fade_out) { - _inverse_fade_out->curve().get_vector (curve_offset, curve_offset + fade_out_limit, gain_buffer, fade_out_limit); + _inverse_fade_out->curve().get_vector (timepos_t (curve_offset), timepos_t (curve_offset + fade_out_limit), gain_buffer, fade_out_limit); /* Fade the data from lower levels in */ for (samplecnt_t n = 0, m = fade_out_offset; n < fade_out_limit; ++n, ++m) { @@ -673,7 +676,7 @@ AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, /* fetch the actual fade out */ - _fade_out->curve().get_vector (curve_offset, curve_offset + fade_out_limit, gain_buffer, fade_out_limit); + _fade_out->curve().get_vector (timepos_t (curve_offset), timepos_t (curve_offset + fade_out_limit), gain_buffer, fade_out_limit); } else { @@ -682,14 +685,14 @@ AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, * out) for the fade in of lower layers */ - _fade_out->curve().get_vector (curve_offset, curve_offset + fade_out_limit, gain_buffer, fade_out_limit); + _fade_out->curve().get_vector (timepos_t (curve_offset), timepos_t (curve_offset + fade_out_limit), gain_buffer, fade_out_limit); for (samplecnt_t n = 0, m = fade_out_offset; n < fade_out_limit; ++n, ++m) { buf[m] *= 1 - gain_buffer[n]; } } } else { - _fade_out->curve().get_vector (curve_offset, curve_offset + fade_out_limit, gain_buffer, fade_out_limit); + _fade_out->curve().get_vector (timepos_t (curve_offset), timepos_t (curve_offset + fade_out_limit), gain_buffer, fade_out_limit); } /* Mix our newly-read data with whatever was already there, @@ -731,7 +734,7 @@ AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, samplecnt_t AudioRegion::read_from_sources (SourceList const & srcs, samplecnt_t limit, Sample* buf, samplepos_t position, samplecnt_t cnt, uint32_t chan_n) const { - sampleoffset_t const internal_offset = position - _position; + sampleoffset_t const internal_offset = position - _position.val().samples(); if (internal_offset >= limit) { return 0; } @@ -744,7 +747,7 @@ AudioRegion::read_from_sources (SourceList const & srcs, samplecnt_t limit, Samp if (chan_n < n_channels()) { boost::shared_ptr src = boost::dynamic_pointer_cast (srcs[chan_n]); - if (src->read (buf, _start + internal_offset, to_read) != to_read) { + if (src->read (buf, _start.val().samples() + internal_offset, to_read) != to_read) { return 0; /* "read nothing" */ } @@ -761,7 +764,7 @@ AudioRegion::read_from_sources (SourceList const & srcs, samplecnt_t limit, Samp uint32_t channel = chan_n % n_channels(); boost::shared_ptr src = boost::dynamic_pointer_cast (srcs[channel]); - if (src->read (buf, _start + internal_offset, to_read) != to_read) { + if (src->read (buf, _start.val().samples() + internal_offset, to_read) != to_read) { return 0; /* "read nothing" */ } @@ -801,7 +804,7 @@ AudioRegion::state () if (_envelope->size() == 2 && _envelope->front()->value == GAIN_COEFF_UNITY && _envelope->back()->value==GAIN_COEFF_UNITY) { - if (_envelope->front()->when == 0 && _envelope->back()->when == _length) { + if (_envelope->front()->when == 0 && _envelope->back()->when == timepos_t (_length)) { default_env = true; } } @@ -886,7 +889,7 @@ AudioRegion::_set_state (const XMLNode& node, int version, PropertyChange& what_ set_default_envelope (); } - _envelope->truncate_end (_length); + _envelope->truncate_end (timepos_t (_length)); } else if (child->name() == "FadeIn") { @@ -966,20 +969,20 @@ AudioRegion::fade_range (samplepos_t start, samplepos_t end) { samplepos_t s, e; - switch (coverage (start, end)) { - case Evoral::OverlapStart: - trim_front(start); - s = _position; + switch (coverage (timepos_t (start), timepos_t (end))) { + case Temporal::OverlapStart: + trim_front (timepos_t (start)); + s = _position.val().samples(); e = end; set_fade_in (FadeConstantPower, e - s); break; - case Evoral::OverlapEnd: - trim_end(end); + case Temporal::OverlapEnd: + trim_end(timepos_t (end)); s = start; - e = _position + _length; + e = (_position.val() + timepos_t (_length)).samples(); set_fade_out (FadeConstantPower, e - s); break; - case Evoral::OverlapInternal: + case Temporal::OverlapInternal: /* needs addressing, perhaps. Difficult to do if we can't * control one edge of the fade relative to the relevant edge * of the region, which we cannot - fades are currently assumed @@ -994,13 +997,13 @@ AudioRegion::fade_range (samplepos_t start, samplepos_t end) void AudioRegion::set_fade_in_shape (FadeShape shape) { - set_fade_in (shape, (samplecnt_t) _fade_in->when(false)); + set_fade_in (shape, _fade_in->when(false).samples()); } void AudioRegion::set_fade_out_shape (FadeShape shape) { - set_fade_out (shape, (samplecnt_t) _fade_out->when(false)); + set_fade_out (shape, _fade_out->when(false).samples()); } void @@ -1018,9 +1021,9 @@ void AudioRegion::set_fade_in (FadeShape shape, samplecnt_t len) { const ARDOUR::ParameterDescriptor desc(FadeInAutomation); - boost::shared_ptr c1 (new Evoral::ControlList (FadeInAutomation, desc)); - boost::shared_ptr c2 (new Evoral::ControlList (FadeInAutomation, desc)); - boost::shared_ptr c3 (new Evoral::ControlList (FadeInAutomation, desc)); + boost::shared_ptr c1 (new Evoral::ControlList (FadeInAutomation, desc, Temporal::AudioTime)); + boost::shared_ptr c2 (new Evoral::ControlList (FadeInAutomation, desc, Temporal::AudioTime)); + boost::shared_ptr c3 (new Evoral::ControlList (FadeInAutomation, desc, Temporal::AudioTime)); _fade_in->freeze (); _fade_in->clear (); @@ -1030,8 +1033,8 @@ AudioRegion::set_fade_in (FadeShape shape, samplecnt_t len) switch (shape) { case FadeLinear: - _fade_in->fast_simple_add (0.0, GAIN_COEFF_SMALL); - _fade_in->fast_simple_add (len, GAIN_COEFF_UNITY); + _fade_in->fast_simple_add (timepos_t (Temporal::AudioTime), GAIN_COEFF_SMALL); + _fade_in->fast_simple_add (timepos_t (len), GAIN_COEFF_UNITY); reverse_curve (_inverse_fade_in.val(), _fade_in.val()); break; @@ -1052,26 +1055,26 @@ AudioRegion::set_fade_in (FadeShape shape, samplecnt_t len) break; case FadeConstantPower: - _fade_in->fast_simple_add (0.0, GAIN_COEFF_SMALL); + _fade_in->fast_simple_add (timepos_t (Temporal::AudioTime), GAIN_COEFF_SMALL); for (int i = 1; i < num_steps; ++i) { const float dist = i / (num_steps + 1.f); - _fade_in->fast_simple_add (len * dist, sin (dist * M_PI / 2.0)); + _fade_in->fast_simple_add (timepos_t (len * dist), sin (dist * M_PI / 2.0)); } - _fade_in->fast_simple_add (len, GAIN_COEFF_UNITY); + _fade_in->fast_simple_add (timepos_t (len), GAIN_COEFF_UNITY); reverse_curve (_inverse_fade_in.val(), _fade_in.val()); break; case FadeSymmetric: //start with a nearly linear cuve - _fade_in->fast_simple_add (0, 1); - _fade_in->fast_simple_add (0.5 * len, 0.6); + _fade_in->fast_simple_add (timepos_t (Temporal::AudioTime), 1); + _fade_in->fast_simple_add (timepos_t (0.5 * len), 0.6); //now generate a fade-out curve by successively applying a gain drop const double breakpoint = 0.7; //linear for first 70% for (int i = 2; i < 9; ++i) { const float coeff = (1.f - breakpoint) * powf (0.5, i); - _fade_in->fast_simple_add (len * (breakpoint + ((GAIN_COEFF_UNITY - breakpoint) * (double)i / 9.0)), coeff); + _fade_in->fast_simple_add (timepos_t (len * (breakpoint + ((GAIN_COEFF_UNITY - breakpoint) * (double)i / 9.0))), coeff); } - _fade_in->fast_simple_add (len, GAIN_COEFF_SMALL); + _fade_in->fast_simple_add (timepos_t (len), GAIN_COEFF_SMALL); reverse_curve (c3, _fade_in.val()); _fade_in->copy_events (*c3); reverse_curve (_inverse_fade_in.val(), _fade_in.val()); @@ -1101,8 +1104,8 @@ void AudioRegion::set_fade_out (FadeShape shape, samplecnt_t len) { const ARDOUR::ParameterDescriptor desc(FadeOutAutomation); - boost::shared_ptr c1 (new Evoral::ControlList (FadeOutAutomation, desc)); - boost::shared_ptr c2 (new Evoral::ControlList (FadeOutAutomation, desc)); + boost::shared_ptr c1 (new Evoral::ControlList (FadeOutAutomation, desc, Temporal::AudioTime)); + boost::shared_ptr c2 (new Evoral::ControlList (FadeOutAutomation, desc, Temporal::AudioTime)); _fade_out->freeze (); _fade_out->clear (); @@ -1112,8 +1115,8 @@ AudioRegion::set_fade_out (FadeShape shape, samplecnt_t len) switch (shape) { case FadeLinear: - _fade_out->fast_simple_add (0.0, GAIN_COEFF_UNITY); - _fade_out->fast_simple_add (len, GAIN_COEFF_SMALL); + _fade_out->fast_simple_add (timepos_t (Temporal::AudioTime), GAIN_COEFF_UNITY); + _fade_out->fast_simple_add (timepos_t (len), GAIN_COEFF_SMALL); reverse_curve (_inverse_fade_out.val(), _fade_out.val()); break; @@ -1132,26 +1135,26 @@ AudioRegion::set_fade_out (FadeShape shape, samplecnt_t len) case FadeConstantPower: //constant-power fades use a sin/cos relationship //the cutoff is abrupt but it has the benefit of being symmetrical - _fade_out->fast_simple_add (0.0, GAIN_COEFF_UNITY); + _fade_out->fast_simple_add (timepos_t (Temporal::AudioTime), GAIN_COEFF_UNITY); for (int i = 1; i < num_steps; ++i) { const float dist = i / (num_steps + 1.f); - _fade_out->fast_simple_add (len * dist, cos (dist * M_PI / 2.0)); + _fade_out->fast_simple_add (timepos_t (len * dist), cos (dist * M_PI / 2.0)); } - _fade_out->fast_simple_add (len, GAIN_COEFF_SMALL); + _fade_out->fast_simple_add (timepos_t (len), GAIN_COEFF_SMALL); reverse_curve (_inverse_fade_out.val(), _fade_out.val()); break; case FadeSymmetric: //start with a nearly linear cuve - _fade_out->fast_simple_add (0, 1); - _fade_out->fast_simple_add (0.5 * len, 0.6); + _fade_out->fast_simple_add (timepos_t (Temporal::AudioTime), 1); + _fade_out->fast_simple_add (timepos_t (0.5 * len), 0.6); //now generate a fade-out curve by successively applying a gain drop const double breakpoint = 0.7; //linear for first 70% for (int i = 2; i < 9; ++i) { const float coeff = (1.f - breakpoint) * powf (0.5, i); - _fade_out->fast_simple_add (len * (breakpoint + ((GAIN_COEFF_UNITY - breakpoint) * (double)i / 9.0)), coeff); + _fade_out->fast_simple_add (timepos_t (len * (breakpoint + ((GAIN_COEFF_UNITY - breakpoint) * (double)i / 9.0))), coeff); } - _fade_out->fast_simple_add (len, GAIN_COEFF_SMALL); + _fade_out->fast_simple_add (timepos_t (len), GAIN_COEFF_SMALL); reverse_curve (_inverse_fade_out.val(), _fade_out.val()); break; } @@ -1167,19 +1170,19 @@ AudioRegion::set_fade_out (FadeShape shape, samplecnt_t len) void AudioRegion::set_fade_in_length (samplecnt_t len) { - if (len > _length) { - len = _length - 1; + if (len > length_samples()) { + len = length_samples() - 1; } if (len < 64) { len = 64; } - bool changed = _fade_in->extend_to (len); + bool changed = _fade_in->extend_to (timepos_t (len)); if (changed) { if (_inverse_fade_in) { - _inverse_fade_in->extend_to (len); + _inverse_fade_in->extend_to (timepos_t (len)); } _default_fade_in = false; @@ -1190,20 +1193,20 @@ AudioRegion::set_fade_in_length (samplecnt_t len) void AudioRegion::set_fade_out_length (samplecnt_t len) { - if (len > _length) { - len = _length - 1; + if (len > length_samples()) { + len = length_samples() - 1; } if (len < 64) { len = 64; } - bool changed = _fade_out->extend_to (len); + bool changed = _fade_out->extend_to (timepos_t (len)); if (changed) { if (_inverse_fade_out) { - _inverse_fade_out->extend_to (len); + _inverse_fade_out->extend_to (timepos_t (len)); } _default_fade_out = false; @@ -1270,8 +1273,8 @@ AudioRegion::set_default_envelope () { _envelope->freeze (); _envelope->clear (); - _envelope->fast_simple_add (0, GAIN_COEFF_UNITY); - _envelope->fast_simple_add (_length, GAIN_COEFF_UNITY); + _envelope->fast_simple_add (timepos_t (Temporal::AudioTime), GAIN_COEFF_UNITY); + _envelope->fast_simple_add (timepos_t (_length), GAIN_COEFF_UNITY); _envelope->thaw (); } @@ -1283,7 +1286,7 @@ AudioRegion::recompute_at_end () */ _envelope->freeze (); - _envelope->truncate_end (_length); + _envelope->truncate_end (timepos_t (_length)); _envelope->thaw (); suspend_property_changes(); @@ -1292,12 +1295,12 @@ AudioRegion::recompute_at_end () set_default_fade_out (); _left_of_split = false; } else if (_fade_out->when(false) > _length) { - _fade_out->extend_to (_length); + _fade_out->extend_to (timepos_t (_length)); send_change (PropertyChange (Properties::fade_out)); } if (_fade_in->when(false) > _length) { - _fade_in->extend_to (_length); + _fade_in->extend_to (timepos_t (_length)); send_change (PropertyChange (Properties::fade_in)); } @@ -1317,12 +1320,12 @@ AudioRegion::recompute_at_start () set_default_fade_in (); _right_of_split = false; } else if (_fade_in->when(false) > _length) { - _fade_in->extend_to (_length); + _fade_in->extend_to (timepos_t (_length)); send_change (PropertyChange (Properties::fade_in)); } if (_fade_out->when(false) > _length) { - _fade_out->extend_to (_length); + _fade_out->extend_to (timepos_t (_length)); send_change (PropertyChange (Properties::fade_out)); } @@ -1396,8 +1399,8 @@ AudioRegion::set_scale_amplitude (gain_t g) double AudioRegion::maximum_amplitude (Progress* p) const { - samplepos_t fpos = _start; - samplepos_t const fend = _start + _length; + samplepos_t fpos = start_sample();; + samplepos_t const fend = start_sample() + length_samples(); double maxamp = 0; samplecnt_t const blocksize = 64 * 1024; @@ -1422,7 +1425,7 @@ AudioRegion::maximum_amplitude (Progress* p) const fpos += to_read; if (p) { - p->set_progress (float (fpos - _start) / _length); + p->set_progress (float (fpos - start_sample()) / length_samples()); if (p->cancelled ()) { return -1; } @@ -1435,8 +1438,8 @@ AudioRegion::maximum_amplitude (Progress* p) const double AudioRegion::rms (Progress* p) const { - samplepos_t fpos = _start; - samplepos_t const fend = _start + _length; + samplepos_t fpos = start_sample(); + samplepos_t const fend = start_sample() + length_samples(); uint32_t const n_chan = n_channels (); double rms = 0; @@ -1462,7 +1465,7 @@ AudioRegion::rms (Progress* p) const total += to_read; fpos += to_read; if (p) { - p->set_progress (float (fpos - _start) / _length); + p->set_progress (float (fpos - start_sample()) / length_samples()); if (p->cancelled ()) { return -1; } @@ -1633,13 +1636,13 @@ AudioRegion::add_transient (samplepos_t where) if (where < first_sample () || where >= last_sample ()) { return; } - where -= _position; + where -= position_sample(); if (!_valid_transients) { - _transient_user_start = _start; + _transient_user_start = start_sample(); _valid_transients = true; } - sampleoffset_t offset = _transient_user_start - _start; + sampleoffset_t offset = _transient_user_start - start_sample();; if (where < offset) { if (offset <= 0) { @@ -1663,16 +1666,16 @@ AudioRegion::update_transient (samplepos_t old_position, samplepos_t new_positio { bool changed = false; if (!_onsets.empty ()) { - const samplepos_t p = old_position - _position; + const samplepos_t p = old_position - position_sample(); AnalysisFeatureList::iterator x = std::find (_onsets.begin (), _onsets.end (), p); if (x != _transients.end ()) { - (*x) = new_position - _position; + (*x) = new_position - position_sample(); changed = true; } } if (_valid_transients) { - const sampleoffset_t offset = _position + _transient_user_start - _start; + const sampleoffset_t offset = position_sample() + _transient_user_start - start_sample(); const samplepos_t p = old_position - offset; AnalysisFeatureList::iterator x = std::find (_user_transients.begin (), _user_transients.end (), p); if (x != _transients.end ()) { @@ -1691,7 +1694,7 @@ AudioRegion::remove_transient (samplepos_t where) { bool changed = false; if (!_onsets.empty ()) { - const samplepos_t p = where - _position; + const samplepos_t p = where - position_sample(); AnalysisFeatureList::iterator i = std::find (_onsets.begin (), _onsets.end (), p); if (i != _onsets.end ()) { _onsets.erase (i); @@ -1700,7 +1703,7 @@ AudioRegion::remove_transient (samplepos_t where) } if (_valid_transients) { - const samplepos_t p = where - (_position + _transient_user_start - _start); + const samplepos_t p = where - (position_sample() + _transient_user_start - start_sample()); AnalysisFeatureList::iterator i = std::find (_user_transients.begin (), _user_transients.end (), p); if (i != _user_transients.end ()) { _user_transients.erase (i); @@ -1751,11 +1754,11 @@ AudioRegion::build_transients () /* find the set of transients within the bounds of this region */ AnalysisFeatureList::iterator low = lower_bound ((*s)->transients.begin(), (*s)->transients.end(), - _start); + start_sample()); AnalysisFeatureList::iterator high = upper_bound ((*s)->transients.begin(), (*s)->transients.end(), - _start + _length); + start_sample() + length_samples()); /* and add them */ _transients.insert (_transients.end(), low, high); @@ -1765,11 +1768,11 @@ AudioRegion::build_transients () /* translate all transients to current position */ for (AnalysisFeatureList::iterator x = _transients.begin(); x != _transients.end(); ++x) { - (*x) -= _start; + (*x) -= start_sample(); } - _transient_analysis_start = _start; - _transient_analysis_end = _start + _length; + _transient_analysis_start = start_sample(); + _transient_analysis_end = start_sample() + length_samples(); return; } @@ -1816,8 +1819,8 @@ in this and future transient-detection operations.\n\ } TransientDetector::cleanup_transients (_transients, pl->session().sample_rate(), 3.0); - _transient_analysis_start = _start; - _transient_analysis_end = _start + _length; + _transient_analysis_start = start_sample(); + _transient_analysis_end = start_sample() + length_samples(); } /* Transient analysis uses ::read() which is relative to _start, @@ -1846,21 +1849,21 @@ AudioRegion::get_transients (AnalysisFeatureList& results) return; } - Region::merge_features (results, _user_transients, _position + _transient_user_start - _start); + Region::merge_features (results, _user_transients, position_sample() + _transient_user_start - start_sample()); if (!_onsets.empty ()) { // onsets are invalidated when start or length changes - merge_features (results, _onsets, _position); + merge_features (results, _onsets, position_sample()); return; } if ((_transient_analysis_start == _transient_analysis_end) - || _transient_analysis_start > _start - || _transient_analysis_end < _start + _length) { + || _transient_analysis_start > start_sample() + || _transient_analysis_end < start_sample() + length_samples()) { build_transients (); } - merge_features (results, _transients, _position + _transient_analysis_start - _start); + merge_features (results, _transients, position_sample() + _transient_analysis_start - start_sample()); } /** Find areas of `silence' within a region. @@ -1880,13 +1883,13 @@ AudioRegion::find_silence (Sample threshold, samplecnt_t min_length, samplecnt_t assert (fade_length >= 0); assert (min_length > 0); - samplepos_t pos = _start; - samplepos_t const end = _start + _length; + samplepos_t pos = start_sample(); + samplepos_t const end = start_sample() + length_samples(); AudioIntervalResult silent_periods; bool in_silence = true; - sampleoffset_t silence_start = _start; + sampleoffset_t silence_start = start_sample(); while (pos < end && !itt.cancel) { @@ -1922,7 +1925,7 @@ AudioRegion::find_silence (Sample threshold, samplecnt_t min_length, samplecnt_t } pos += cur_samples; - itt.progress = (end - pos) / (double)_length; + itt.progress = (end - pos) / (double) length_samples(); if (cur_samples == 0) { assert (pos >= end); @@ -1942,10 +1945,10 @@ AudioRegion::find_silence (Sample threshold, samplecnt_t min_length, samplecnt_t return silent_periods; } -Evoral::Range +Temporal::Range AudioRegion::body_range () const { - return Evoral::Range (first_sample() + _fade_in->when(false) + 1, last_sample() - _fade_out->when(false)); + return Temporal::Range ((nt_position() + _fade_in->back()->when).increment(), nt_end().earlier (_fade_out->back()->when)); } boost::shared_ptr @@ -1963,9 +1966,9 @@ AudioRegion::get_single_other_xfade_region (bool start) const boost::shared_ptr rl; if (start) { - rl = pl->regions_at (position()); + rl = pl->regions_at (nt_position()); } else { - rl = pl->regions_at (last_sample()); + rl = pl->regions_at (nt_last()); } RegionList::iterator i; @@ -2005,7 +2008,7 @@ AudioRegion::verify_xfade_bounds (samplecnt_t len, bool start) /* zero or > 2 regions here, don't care about len, but it can't be longer than the region itself. */ - return min (length(), len); + return min (length_samples(), len); } /* we overlap a single region. clamp the length of an xfade to @@ -2014,12 +2017,11 @@ AudioRegion::verify_xfade_bounds (samplecnt_t len, bool start) */ if (start) { - maxlen = other->latest_possible_sample() - position(); + maxlen = other->latest_possible_sample() - position_sample(); } else { - maxlen = last_sample() - other->earliest_possible_position(); + maxlen = last_sample() - other->earliest_possible_position().samples(); } - return min (length(), min (maxlen, len)); + return min (length_samples(), min (maxlen, len)); } - diff --git a/libs/ardour/audiosource.cc b/libs/ardour/audiosource.cc index b5bd48c12c..dfc517c5da 100644 --- a/libs/ardour/audiosource.cc +++ b/libs/ardour/audiosource.cc @@ -81,7 +81,6 @@ bool AudioSource::_build_peakfiles = false; AudioSource::AudioSource (Session& s, const string& name) : Source (s, DataType::AUDIO, name) - , _length (0) , _peak_byte_max (0) , _peaks_built (false) , _peakfile_fd (-1) @@ -98,7 +97,6 @@ AudioSource::AudioSource (Session& s, const string& name) AudioSource::AudioSource (Session& s, const XMLNode& node) : Source (s, node) - , _length (0) , _peak_byte_max (0) , _peaks_built (false) , _peakfile_fd (-1) @@ -151,20 +149,8 @@ AudioSource::set_state (const XMLNode& node, int /*version*/) return 0; } -bool -AudioSource::empty () const -{ - return _length == 0; -} - -samplecnt_t -AudioSource::length (samplepos_t /*pos*/) const -{ - return _length; -} - void -AudioSource::update_length (samplecnt_t len) +AudioSource::update_length (timecnt_t const & len) { if (len > _length) { _length = len; @@ -271,7 +257,7 @@ AudioSource::initialize_peakfile (const string& audio_path, const bool in_sessio /* we found it in the peaks dir, so check it out */ - if (statbuf.st_size == 0 || (statbuf.st_size < (off_t) ((length(_natural_position) / _FPP) * sizeof (PeakData)))) { + if (statbuf.st_size == 0 || (statbuf.st_size < (off_t) ((length().samples() / _FPP) * sizeof (PeakData)))) { DEBUG_TRACE(DEBUG::Peaks, string_compose("Peakfile %1 is empty\n", _peakpath)); _peaks_built = false; } else { @@ -425,7 +411,7 @@ AudioSource::read_peaks_with_fpp (PeakData *peaks, samplecnt_t npeaks, samplepos * */ - const off_t expected_file_size = (_length / (double) samples_per_file_peak) * sizeof (PeakData); + const off_t expected_file_size = (_length.samples() / (double) samples_per_file_peak) * sizeof (PeakData); if (statbuf.st_size < expected_file_size) { warning << string_compose (_("peak file %1 is truncated from %2 to %3"), _peakpath, expected_file_size, statbuf.st_size) << endmsg; @@ -457,9 +443,9 @@ AudioSource::read_peaks_with_fpp (PeakData *peaks, samplecnt_t npeaks, samplepos /* fix for near-end-of-file conditions */ - if (cnt + start > _length) { + if (cnt + start > _length.samples()) { // cerr << "too close to end @ " << _length << " given " << start << " + " << cnt << " (" << _length - start << ")" << endl; - cnt = std::max ((samplecnt_t)0, _length - start); + cnt = std::max ((samplecnt_t)0, _length.samples() - start); read_npeaks = min ((samplecnt_t) floor (cnt / samples_per_visual_peak), npeaks); zero_fill = npeaks - read_npeaks; expected_peaks = (cnt / (double) samples_per_file_peak); @@ -704,9 +690,9 @@ AudioSource::read_peaks_with_fpp (PeakData *peaks, samplecnt_t npeaks, samplepos if (i == samples_read) { - to_read = min (chunksize, (samplecnt_t)(_length - current_sample)); + to_read = min (chunksize, (samplecnt_t)(_length.samples() - current_sample)); - if (current_sample >= _length) { + if (current_sample >= _length.samples()) { /* hmm, error condition - we've reached the end of the file * without generating all the peak data. cook up a zero-filled @@ -719,7 +705,7 @@ AudioSource::read_peaks_with_fpp (PeakData *peaks, samplecnt_t npeaks, samplepos } else { - to_read = min (chunksize, (_length - current_sample)); + to_read = min (chunksize, (_length.samples() - current_sample)); if ((samples_read = read_unlocked (raw_staging.get(), current_sample, to_read)) == 0) { @@ -779,7 +765,7 @@ AudioSource::build_peaks_from_scratch () } samplecnt_t current_sample = 0; - samplecnt_t cnt = _length; + samplecnt_t cnt = _length.samples(); _peaks_built = false; boost::scoped_array buf(new Sample[bufsize]); @@ -1112,7 +1098,7 @@ samplecnt_t AudioSource::available_peaks (double zoom_factor) const { if (zoom_factor < _FPP) { - return length(_natural_position); // peak data will come from the audio file + return _length.samples(); // peak data will come from the audio file } /* peak data comes from peakfile, but the filesize might not represent diff --git a/libs/ardour/auditioner.cc b/libs/ardour/auditioner.cc index cd908bc9e9..2c1f3c8976 100644 --- a/libs/ardour/auditioner.cc +++ b/libs/ardour/auditioner.cc @@ -308,16 +308,17 @@ Auditioner::audition_region (boost::shared_ptr region) unload_synth (true); midi_region.reset(); - _import_position = 0; + _import_position = timepos_t (Temporal::AudioTime); /* copy it */ + the_region = boost::dynamic_pointer_cast (RegionFactory::create (region, false)); - the_region->set_position (0); + the_region->set_position (timepos_t (Temporal::AudioTime)); _disk_reader->midi_playlist()->drop_regions (); _disk_reader->audio_playlist()->drop_regions (); - _disk_reader->audio_playlist()->add_region (the_region, 0, 1); + _disk_reader->audio_playlist()->add_region (the_region, timepos_t (Temporal::AudioTime), 1); ProcessorStreams ps; { @@ -325,7 +326,7 @@ Auditioner::audition_region (boost::shared_ptr region) if (configure_processors (&ps)) { error << string_compose (_("Cannot setup auditioner processing flow for %1 channels"), - region->n_channels()) << endmsg; + region->sources().size()) << endmsg; return; } } @@ -334,7 +335,7 @@ Auditioner::audition_region (boost::shared_ptr region) _midi_audition = true; the_region.reset(); - _import_position = region->position(); + _import_position = region->nt_position(); /* copy it */ midi_region = (boost::dynamic_pointer_cast (RegionFactory::create (region, false))); @@ -362,7 +363,7 @@ Auditioner::audition_region (boost::shared_ptr region) if (configure_processors (&ps)) { error << string_compose (_("Cannot setup auditioner processing flow for %1 channels"), - region->n_channels()) << endmsg; + region->sources().size()) << endmsg; unload_synth (true); return; } @@ -380,13 +381,13 @@ Auditioner::audition_region (boost::shared_ptr region) _seeking = false; int dir; - samplecnt_t offset; + timepos_t offset; if (_midi_audition) { - length = midi_region->length(); + length = midi_region->nt_length(); offset = _import_position + midi_region->sync_offset (dir); } else { - length = the_region->length(); + length = the_region->nt_length(); offset = the_region->sync_offset (dir); } @@ -402,7 +403,7 @@ Auditioner::audition_region (boost::shared_ptr region) offset = 0; } - _disk_reader->seek (offset, true); + _disk_reader->seek (offset.samples(), true); if (_midi_audition) { /* Fill MIDI buffers. @@ -415,7 +416,7 @@ Auditioner::audition_region (boost::shared_ptr region) _disk_reader->overwrite_existing_buffers (); } - current_sample = offset; + current_sample = offset.samples(); g_atomic_int_set (&_auditioning, 1); } @@ -455,7 +456,7 @@ Auditioner::play_audition (samplecnt_t nframes) if(!_seeking) { /* process audio */ - this_nframes = min (nframes, length - current_sample + _import_position); + this_nframes = min (nframes, length.samples() - current_sample + _import_position.samples()); if (this_nframes > 0 && 0 != (ret = roll (this_nframes, current_sample, current_sample + this_nframes, need_butler))) { silence (nframes); @@ -475,7 +476,7 @@ Auditioner::play_audition (samplecnt_t nframes) silence (nframes); } - if (_seek_sample >= 0 && _seek_sample < length && !_seeking) { + if (_seek_sample >= 0 && _seek_sample < length.samples() && !_seeking) { _queue_panic = true; _seek_complete = false; _seeking = true; @@ -483,10 +484,10 @@ Auditioner::play_audition (samplecnt_t nframes) } if (!_seeking) { - AuditionProgress(current_sample - _import_position, length); /* emit */ + AuditionProgress(current_sample - _import_position.samples(), length.samples()); /* emit */ } - if (current_sample >= length + _import_position) { + if (current_sample >= (length + _import_position).samples()) { _session.cancel_audition (); unload_synth (false); return 0; @@ -515,7 +516,7 @@ Auditioner::seek_to_sample (sampleoffset_t pos) { void Auditioner::seek_to_percent (float const pos) { if (_seek_sample < 0 && !_seeking) { - _seek_sample = floorf(length * pos / 100.0); + _seek_sample = floorf(length.samples() * pos / 100.0); } } diff --git a/libs/ardour/automatable.cc b/libs/ardour/automatable.cc index 7649f36bcb..741261d5d7 100644 --- a/libs/ardour/automatable.cc +++ b/libs/ardour/automatable.cc @@ -22,6 +22,8 @@ */ #include +#include + #include #include "pbd/gstdio_compat.h" @@ -29,6 +31,8 @@ #include "pbd/error.h" +#include "temporal/timeline.h" + #include "ardour/amp.h" #include "ardour/automatable.h" #include "ardour/event_type_map.h" @@ -116,9 +120,9 @@ Automatable::load_automation (const string& path) fullpath += path; } - FILE * in = g_fopen (fullpath.c_str (), "rb"); + std::ifstream in (fullpath); - if (!in) { + if (in.bad()) { warning << string_compose(_("cannot open %2 to load automation data (%3)") , fullpath, strerror (errno)) << endmsg; return 1; @@ -128,17 +132,14 @@ Automatable::load_automation (const string& path) set tosave; controls().clear (); - while (!feof(in)) { - double when; + while (!in.eof()) { + Temporal::timepos_t when; double value; uint32_t port; - if (3 != fscanf (in, "%d %lf %lf", &port, &when, &value)) { - if (feof(in)) { - break; - } - goto bad; - } + in >> port; if (in.bad()) { goto bad; } + in >> when; if (in.bad()) { goto bad; } + in >> value; if (in.bad()) { goto bad; } Evoral::Parameter param(PluginAutomation, 0, port); /* FIXME: this is legacy and only used for plugin inserts? I think? */ @@ -146,14 +147,12 @@ Automatable::load_automation (const string& path) c->list()->add (when, value); tosave.insert (param); } - ::fclose (in); return 0; bad: error << string_compose(_("cannot load automation data from %2"), fullpath) << endmsg; controls().clear (); - ::fclose (in); return -1; } @@ -404,23 +403,24 @@ Automatable::non_realtime_locate (samplepos_t now) * compare to compare to non_realtime_transport_stop() */ const bool list_did_write = !l->in_new_write_pass (); - c->stop_touch (-1); // time is irrelevant - l->stop_touch (-1); +#warning NUTEMPO check use of domain in arbitrary irrelevant time + c->stop_touch (timepos_t::zero (Temporal::AudioTime)); // time is irrelevant + l->stop_touch (timepos_t::zero (Temporal::AudioTime)); c->commit_transaction (list_did_write); - l->write_pass_finished (now, Config->get_automation_thinning_factor ()); + l->write_pass_finished (timepos_t (now), Config->get_automation_thinning_factor ()); if (l->automation_state () == Write) { l->set_automation_state (Touch); } if (l->automation_playback ()) { - c->set_value_unchecked (c->list ()->eval (now)); + c->set_value_unchecked (c->list ()->eval (timepos_t (now))); } } - l->start_write_pass (now); + l->start_write_pass (timepos_t (now)); if (rolling && am_touching) { - c->start_touch (now); + c->start_touch (timepos_t (now)); } } } @@ -450,19 +450,19 @@ Automatable::non_realtime_transport_stop (samplepos_t now, bool /*flush_processo */ const bool list_did_write = !l->in_new_write_pass (); - c->stop_touch (now); - l->stop_touch (now); + c->stop_touch (timepos_t (now)); + l->stop_touch (timepos_t (now)); c->commit_transaction (list_did_write); - l->write_pass_finished (now, Config->get_automation_thinning_factor ()); + l->write_pass_finished (timepos_t (now), Config->get_automation_thinning_factor ()); if (l->automation_state () == Write) { l->set_automation_state (Touch); } if (l->automation_playback ()) { - c->set_value_unchecked (c->list ()->eval (now)); + c->set_value_unchecked (c->list ()->eval (timepos_t (now))); } } } @@ -547,7 +547,7 @@ Automatable::control_factory(const Evoral::Parameter& param) if (!Variant::type_is_numeric(desc.datatype)) { make_list = false; // Can't automate non-numeric data yet } else { - list = boost::shared_ptr(new AutomationList(param, desc)); + list = boost::shared_ptr(new AutomationList(param, desc, Temporal::AudioTime)); } control = new PluginInsert::PluginPropertyControl(pi, param, desc, list); } @@ -593,7 +593,8 @@ Automatable::control_factory(const Evoral::Parameter& param) } if (make_list && !list) { - list = boost::shared_ptr(new AutomationList(param, desc)); +#warning NUTEMPO what time domain to use here? + list = boost::shared_ptr(new AutomationList(param, desc, Temporal::AudioTime)); } if (!control) { @@ -638,7 +639,7 @@ Automatable::clear_controls () } bool -Automatable::find_next_event (double start, double end, Evoral::ControlEvent& next_event, bool only_active) const +Automatable::find_next_event (timepos_t const & start, timepos_t const & end, Evoral::ControlEvent& next_event, bool only_active) const { next_event.when = start <= end ? std::numeric_limits::max() : 0; @@ -670,7 +671,7 @@ Automatable::find_next_event (double start, double end, Evoral::ControlEvent& ne } void -Automatable::find_next_ac_event (boost::shared_ptr c, double start, double end, Evoral::ControlEvent& next_event) const +Automatable::find_next_ac_event (boost::shared_ptr c, timepos_t const & start, timepos_t const & end, Evoral::ControlEvent& next_event) const { assert (start <= end); @@ -697,7 +698,7 @@ Automatable::find_next_ac_event (boost::shared_ptr c, double } void -Automatable::find_prev_ac_event (boost::shared_ptr c, double start, double end, Evoral::ControlEvent& next_event) const +Automatable::find_prev_ac_event (boost::shared_ptr c, timepos_t const & start, timepos_t const & end, Evoral::ControlEvent& next_event) const { assert (start > end); boost::shared_ptr sc diff --git a/libs/ardour/automation_control.cc b/libs/ardour/automation_control.cc index 56f7b1be3a..dc8b6f41d8 100644 --- a/libs/ardour/automation_control.cc +++ b/libs/ardour/automation_control.cc @@ -100,7 +100,7 @@ double AutomationControl::get_value() const { bool from_list = alist() && alist()->automation_playback(); - return Control::get_double (from_list, _session.transport_sample()); + return Control::get_double (from_list, timepos_t (_session.transport_sample())); } double @@ -128,7 +128,7 @@ AutomationControl::set_value (double val, PBD::Controllable::GroupControlDisposi } if (_list && !touching () && alist()->automation_state() == Latch && _session.transport_rolling ()) { - start_touch (_session.transport_sample ()); + start_touch (timepos_t (_session.transport_sample ())); } /* enforce strict double/boolean value mapping */ @@ -170,7 +170,7 @@ AutomationControl::automation_run (samplepos_t start, pframes_t nframes) assert (_list); bool valid = false; - double val = _list->rt_safe_eval (start, valid); + double val = _list->rt_safe_eval (timepos_t (start), valid); if (!valid) { return; } @@ -216,7 +216,7 @@ AutomationControl::actually_set_value (double value, PBD::Controllable::GroupCon to_list = false; } - Control::set_double (value, pos, to_list); + Control::set_double (value, timepos_t (pos), to_list); if (old_value != (float)value) { #if 0 @@ -254,9 +254,10 @@ AutomationControl::set_automation_state (AutoState as) if (as == Write) { AutomationWatch::instance().add_automation_watch (boost::dynamic_pointer_cast(shared_from_this())); } else if (as & (Touch | Latch)) { +#warning NUTEMPO fixme timestamps here are always in samples ... should match list time domain if (alist()->empty()) { - Control::set_double (val, _session.current_start_sample (), true); - Control::set_double (val, _session.current_end_sample (), true); + Control::set_double (val, timepos_t (_session.current_start_sample ()), true); + Control::set_double (val, timepos_t (_session.current_end_sample ()), true); Changed (true, Controllable::NoGroup); } if (!touching()) { @@ -277,7 +278,7 @@ AutomationControl::set_automation_state (AutoState as) } void -AutomationControl::start_touch (double when) +AutomationControl::start_touch (timepos_t const & when) { if (!_list || touching ()) { return; @@ -300,7 +301,7 @@ AutomationControl::start_touch (double when) } void -AutomationControl::stop_touch (double when) +AutomationControl::stop_touch (timepos_t const & when) { if (!_list || !touching ()) { return; diff --git a/libs/ardour/automation_list.cc b/libs/ardour/automation_list.cc index 2208cc8924..0d51bdfdb4 100644 --- a/libs/ardour/automation_list.cc +++ b/libs/ardour/automation_list.cc @@ -28,6 +28,8 @@ #include #include +#include "temporal/types_convert.h" + #include "ardour/automation_list.h" #include "ardour/beats_samples_converter.h" #include "ardour/event_type_map.h" @@ -60,8 +62,8 @@ static void dumpit (const AutomationList& al, string prefix = "") cerr << "\n"; } #endif -AutomationList::AutomationList (const Evoral::Parameter& id, const Evoral::ParameterDescriptor& desc) - : ControlList(id, desc) +AutomationList::AutomationList (const Evoral::Parameter& id, const Evoral::ParameterDescriptor& desc, Temporal::TimeDomain time_domain) + : ControlList(id, desc, time_domain) , _before (0) { _state = Off; @@ -74,8 +76,8 @@ AutomationList::AutomationList (const Evoral::Parameter& id, const Evoral::Param AutomationListCreated(this); } -AutomationList::AutomationList (const Evoral::Parameter& id) - : ControlList(id, ARDOUR::ParameterDescriptor(id)) +AutomationList::AutomationList (const Evoral::Parameter& id, Temporal::TimeDomain time_domain) + : ControlList(id, ARDOUR::ParameterDescriptor(id), time_domain) , _before (0) { _state = Off; @@ -102,7 +104,7 @@ AutomationList::AutomationList (const AutomationList& other) AutomationListCreated(this); } -AutomationList::AutomationList (const AutomationList& other, double start, double end) +AutomationList::AutomationList (const AutomationList& other, timepos_t const & start, timepos_t const & end) : ControlList(other, start, end) , _before (0) { @@ -119,7 +121,7 @@ AutomationList::AutomationList (const AutomationList& other, double start, doubl * in or below the AutomationList node. It is used if @param id is non-null. */ AutomationList::AutomationList (const XMLNode& node, Evoral::Parameter id) - : ControlList(id, ARDOUR::ParameterDescriptor(id)) + : ControlList(id, ARDOUR::ParameterDescriptor(id), Temporal::AudioTime) /* domain may change in ::set_state */ , _before (0) { g_atomic_int_set (&_touching, 0); @@ -145,9 +147,10 @@ AutomationList::~AutomationList() boost::shared_ptr AutomationList::create(const Evoral::Parameter& id, - const Evoral::ParameterDescriptor& desc) + const Evoral::ParameterDescriptor& desc, + Temporal::TimeDomain time_domain) { - return boost::shared_ptr(new AutomationList(id, desc)); + return boost::shared_ptr(new AutomationList(id, desc, time_domain)); } void @@ -245,20 +248,20 @@ AutomationList::default_interpolation () const } void -AutomationList::start_write_pass (double when) +AutomationList::start_write_pass (timepos_t const & when) { snapshot_history (true); ControlList::start_write_pass (when); } void -AutomationList::write_pass_finished (double when, double thinning_factor) +AutomationList::write_pass_finished (timepos_t const & when, double thinning_factor) { ControlList::write_pass_finished (when, thinning_factor); } void -AutomationList::start_touch (double when) +AutomationList::start_touch (timepos_t const & when) { if (_state == Touch) { start_write_pass (when); @@ -268,7 +271,7 @@ AutomationList::start_touch (double when) } void -AutomationList::stop_touch (double) +AutomationList::stop_touch (timepos_t const & /* not used */) { if (g_atomic_int_get (&_touching) == 0) { /* this touch has already been stopped (probably by Automatable::transport_stopped), @@ -315,26 +318,27 @@ AutomationList::thaw () } bool -AutomationList::paste (const ControlList& alist, double pos, BeatsSamplesConverter const& bfc) +AutomationList::paste (const ControlList& alist, timepos_t const & pos, BeatsSamplesConverter const& bfc) { - AutomationType src_type = (AutomationType)alist.parameter().type(); - AutomationType dst_type = (AutomationType)_parameter.type(); - - if (parameter_is_midi (src_type) == parameter_is_midi (dst_type)) { + if (time_domain() == alist.time_domain()) { return ControlList::paste (alist, pos); } - bool to_sample = parameter_is_midi (src_type); + + /* time domains differ - need to map the time of all points in alist + * into our time domain + */ + + const bool to_sample = (time_domain() == Temporal::AudioTime); ControlList cl (alist); cl.clear (); + for (const_iterator i = alist.begin ();i != alist.end (); ++i) { - double when = (*i)->when; if (to_sample) { - when = bfc.to (Temporal::Beats::from_double ((*i)->when)); + cl.fast_simple_add (timepos_t ((*i)->when.samples()), (*i)->value); } else { - when = bfc.from ((*i)->when).to_double (); + cl.fast_simple_add (timepos_t ((*i)->when.beats ()), (*i)->value); } - cl.fast_simple_add (when, (*i)->value); } return ControlList::paste (cl, pos); } @@ -359,6 +363,7 @@ AutomationList::state (bool save_auto_state, bool need_lock) root->set_property ("automation-id", EventTypeMap::instance().to_symbol(_parameter)); root->set_property ("id", id()); root->set_property ("interpolation-style", _interpolation); + root->set_property ("time-domain", enum_2_string (time_domain())); if (save_auto_state) { /* never serialize state with Write enabled - too dangerous @@ -432,13 +437,13 @@ AutomationList::deserialize_events (const XMLNode& node) std::string x_str; std::string y_str; - double x; + timepos_t x; double y; bool ok = true; while (str) { str >> x_str; - if (!str || !PBD::string_to (x_str, x)) { + if (!str || !PBD::string_to (x_str, x)) { break; } str >> y_str; @@ -469,6 +474,11 @@ AutomationList::set_state (const XMLNode& node, int version) XMLNodeList nlist = node.children(); XMLNode* nsos; XMLNodeIterator niter; + Temporal::TimeDomain time_domain; + + if (node.get_property ("time-domain", time_domain)) { + set_time_domain (time_domain); + } if (node.name() == X_("events")) { /* partial state setting*/ @@ -505,7 +515,7 @@ AutomationList::set_state (const XMLNode& node, int version) } y = std::min ((double)_desc.upper, std::max ((double)_desc.lower, y)); - fast_simple_add (x, y); + fast_simple_add (timepos_t (x), y); } thaw (); diff --git a/libs/ardour/automation_watch.cc b/libs/ardour/automation_watch.cc index 763e63a3aa..2d0fc199bd 100644 --- a/libs/ardour/automation_watch.cc +++ b/libs/ardour/automation_watch.cc @@ -87,7 +87,8 @@ AutomationWatch::add_automation_watch (boost::shared_ptr ac) DEBUG_TRACE (DEBUG::Automation, string_compose ("\ttransport is rolling @ %1, audible = %2so enter write pass\n", _session->transport_speed(), _session->audible_sample())); /* add a guard point since we are already moving */ - ac->list()->set_in_write_pass (true, true, _session->audible_sample()); +#warning NUTEMPO QUESTION should the time be in the domain of the list ? + ac->list()->set_in_write_pass (true, true, timepos_t (_session->audible_sample())); } /* we can't store shared_ptr in connections because it @@ -142,7 +143,7 @@ AutomationWatch::transport_stop_automation_watches (samplepos_t when) } for (AutomationWatches::iterator i = tmp.begin(); i != tmp.end(); ++i) { - (*i)->stop_touch (when); + (*i)->stop_touch (timepos_t (when)); } } @@ -165,7 +166,7 @@ AutomationWatch::timer () if (sc) { val = sc->reduce_by_masters (val, true); } - (*aw)->list()->add (time, val, true); + (*aw)->list()->add (timepos_t (time), val, true); } } } else if (time != _last_time) { //transport stopped or reversed. stop the automation pass and start a new one (for bonus points, someday store the previous pass in an undo record) @@ -175,7 +176,7 @@ AutomationWatch::timer () (*aw)->alist()->automation_write())); (*aw)->list()->set_in_write_pass (false); if ( (*aw)->alist()->automation_write() ) { - (*aw)->list()->set_in_write_pass (true, true, time); + (*aw)->list()->set_in_write_pass (true, true, timepos_t (time)); } } } diff --git a/libs/ardour/beats_samples_converter.cc b/libs/ardour/beats_samples_converter.cc index f6b8c1e495..61d8377f88 100644 --- a/libs/ardour/beats_samples_converter.cc +++ b/libs/ardour/beats_samples_converter.cc @@ -18,16 +18,17 @@ #include "pbd/stacktrace.h" +#include "temporal/tempo.h" + #include "ardour/beats_samples_converter.h" -#include "ardour/tempo.h" namespace ARDOUR { /** Takes a positive duration in quarter-note beats and considers it as a distance from the origin - * supplied to the constructor. Returns the equivalent number of samples, + * supplied to the constructor. Returns the equivalent number of samples, * taking tempo changes into account. */ -samplepos_t +samplecnt_t BeatsSamplesConverter::to (Temporal::Beats beats) const { if (beats < Temporal::Beats()) { @@ -35,37 +36,17 @@ BeatsSamplesConverter::to (Temporal::Beats beats) const PBD::stacktrace (std::cerr, 30); return 0; } - return _tempo_map.samplepos_plus_qn (_origin_b, beats) - _origin_b; + return _tempo_map.sample_quarters_delta_as_samples (_origin, beats) - _origin; } -/** Takes a duration in samples and considers it as a distance from the origin - * supplied to the constructor. Returns the equivalent number of quarter-note beats, +/** Takes a positive duration in superclocks and considers it as a distance from the origin + * supplied to the constructor. Returns the equivalent number of quarter-note beats, * taking tempo changes into account. + * + * Distance must be positive because we assume we are walking forward from our origin. */ Temporal::Beats -BeatsSamplesConverter::from (samplepos_t samples) const +BeatsSamplesConverter::from (samplecnt_t distance) const { - return _tempo_map.framewalk_to_qn (_origin_b, samples); + return _tempo_map.sample_delta_as_quarters (_origin, distance); } - -/** As above, but with quarter-note beats in double instead (for GUI). */ -samplepos_t -DoubleBeatsSamplesConverter::to (double beats) const -{ - if (beats < 0.0) { - std::cerr << "negative beats passed to BFC: " << beats << std::endl; - PBD::stacktrace (std::cerr, 30); - return 0; - } - return _tempo_map.samplepos_plus_qn (_origin_b, Temporal::Beats(beats)) - _origin_b; -} - -/** As above, but with quarter-note beats in double instead (for GUI). */ -double -DoubleBeatsSamplesConverter::from (samplepos_t samples) const -{ - return _tempo_map.framewalk_to_qn (_origin_b, samples).to_double(); -} - -} /* namespace ARDOUR */ - diff --git a/libs/ardour/convolver.cc b/libs/ardour/convolver.cc index 112db53e2b..2db7e029a9 100644 --- a/libs/ardour/convolver.cc +++ b/libs/ardour/convolver.cc @@ -56,7 +56,7 @@ bool Convolution::add_impdata ( uint32_t c_in, uint32_t c_out, - boost::shared_ptr readable, + boost::shared_ptr readable, float gain, uint32_t pre_delay, sampleoffset_t offset, @@ -66,7 +66,7 @@ Convolution::add_impdata ( if (_configured || c_in >= _n_inputs || c_out >= _n_outputs) { return false; } - if (!readable || readable->readable_length () <= offset || readable->n_channels () <= channel) { + if (!readable || readable->readable_length_samples () <= offset || readable->n_channels () <= channel) { return false; } @@ -104,7 +104,7 @@ Convolution::restart () _max_size = 0; for (std::vector::const_iterator i = _impdata.begin (); i != _impdata.end (); ++i) { - _max_size = std::max (_max_size, (uint32_t)i->readable_length ()); + _max_size = std::max (_max_size, (uint32_t)i->readable_length_samples ()); } int rv = _convproc.configure ( @@ -121,7 +121,7 @@ Convolution::restart () const float ir_gain = i->gain; const uint32_t ir_delay = i->delay; - const uint32_t ir_len = i->readable_length (); + const uint32_t ir_len = i->readable_length_samples (); while (true) { float ir[8192]; @@ -235,14 +235,14 @@ Convolver::Convolver ( { _threaded = true; - std::vector > readables = Readable::load (_session, path); + std::vector > readables = AudioReadable::load (_session, path); if (readables.empty ()) { PBD::error << string_compose (_("Convolver: IR \"%1\" no usable audio-channels sound."), path) << endmsg; throw failed_constructor (); } - if (readables[0]->readable_length () > 0x1000000 /*2^24*/) { + if (readables[0]->readable_length_samples () > 0x1000000 /*2^24*/) { PBD::error << string_compose (_("Convolver: IR \"%1\" file too long."), path) << endmsg; throw failed_constructor (); } @@ -297,7 +297,7 @@ Convolver::Convolver ( io_i = (c / n_outputs ()) % n_inputs (); } - boost::shared_ptr r = readables[ir_c]; + boost::shared_ptr r = readables[ir_c]; assert (r->n_channels () == 1); const float chan_gain = _ir_settings.gain * _ir_settings.channel_gain[c]; diff --git a/libs/ardour/disk_io.cc b/libs/ardour/disk_io.cc index 8af3dd0c4c..a71f8d3780 100644 --- a/libs/ardour/disk_io.cc +++ b/libs/ardour/disk_io.cc @@ -349,14 +349,14 @@ DiskIOProcessor::ChannelInfo::~ChannelInfo () */ void DiskIOProcessor::get_location_times(const Location* location, - samplepos_t* start, - samplepos_t* end, - samplepos_t* length) + timepos_t* start, + timepos_t* end, + timecnt_t* length) { if (location) { *start = location->start(); *end = location->end(); - *length = *end - *start; + *length = location->length(); } } diff --git a/libs/ardour/disk_reader.cc b/libs/ardour/disk_reader.cc index 03d34118a1..f0837b9b3b 100644 --- a/libs/ardour/disk_reader.cc +++ b/libs/ardour/disk_reader.cc @@ -23,7 +23,7 @@ #include "pbd/memento_command.h" #include "pbd/playback_buffer.h" -#include "evoral/Range.h" +#include "temporal/range.h" #include "ardour/amp.h" #include "ardour/audio_buffer.h" @@ -401,8 +401,9 @@ DiskReader::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp samplepos_t ss = start_sample; Location* loc = _loop_location; if (loc) { - Evoral::Range loop_range (loc->start (), loc->end () - 1); - ss = loop_range.squish (playback_sample); + Temporal::Range loop_range (loc->start (), loc->end ()); + ss = loop_range.squish (timepos_t (playback_sample)).samples(); + playback_sample = ss; } if (ss != playback_sample) { if (can_internal_playback_seek (ss - playback_sample)) { @@ -492,8 +493,8 @@ midi: Location* loc = _loop_location; if (loc) { - Evoral::Range loop_range (loc->start (), loc->end () - 1); - playback_sample = loop_range.squish (playback_sample); + Temporal::Range loop_range (loc->start (), loc->end ()); + playback_sample = loop_range.squish (timepos_t (playback_sample)).samples(); } if (_playlists[DataType::AUDIO]) { @@ -990,7 +991,7 @@ DiskReader::audio_read (Sample* sum_buffer, { samplecnt_t this_read = 0; bool reloop = false; - samplepos_t loop_end = 0; + samplepos_t loop_end = 0; samplepos_t loop_start = 0; Location* loc = 0; const samplecnt_t rcnt = cnt; @@ -1008,12 +1009,11 @@ DiskReader::audio_read (Sample* sum_buffer, */ if ((loc = _loop_location) != 0) { - loop_start = loc->start (); - loop_end = loc->end (); + loop_start = loc->start_sample (); + loop_end = loc->end_sample (); - /* Evoral::Range has inclusive range semantics. Ugh. Hence the -1 */ - const Evoral::Range loop_range (loop_start, loop_end - 1); - start = loop_range.squish (start); + const Temporal::Range loop_range (loc->start(), loc->end()); + start = loop_range.squish (timepos_t (start)).samples(); } } else { @@ -1047,7 +1047,7 @@ DiskReader::audio_read (Sample* sum_buffer, * useful after the return from AudioPlayback::read() */ - if (audio_playlist ()->read (sum_buffer, mixdown_buffer, gain_buffer, start, this_read, channel) != this_read) { + if (audio_playlist ()->read (sum_buffer, mixdown_buffer, gain_buffer, timepos_t (start), timecnt_t::from_samples (this_read), channel) != this_read) { error << string_compose (_("DiskReader %1: cannot read %2 from playlist at sample %3"), id (), this_read, start) << endmsg; return 0; } @@ -1066,9 +1066,9 @@ DiskReader::audio_read (Sample* sum_buffer, loop_declick_out.run (sum_buffer, start, start + this_read); break; case XFadeLoop: - if (last_refill_loop_start != loc->start() || rci->pre_loop_buffer == 0) { + if (last_refill_loop_start != loop_start || rci->pre_loop_buffer == 0) { setup_preloop_buffer (); - last_refill_loop_start = loc->start(); + last_refill_loop_start = loop_start; } maybe_xfade_loop (sum_buffer, start, start + this_read, rci); break; @@ -1345,7 +1345,7 @@ out: } void -DiskReader::playlist_ranges_moved (list > const& movements_samples, bool from_undo_or_shift) +DiskReader::playlist_ranges_moved (list const& movements, bool from_undo_or_shift) { /* If we're coming from an undo, it will have handled * automation undo (it must, since automation-follows-regions @@ -1364,14 +1364,6 @@ DiskReader::playlist_ranges_moved (list > const& return; } - list > movements; - - for (list >::const_iterator i = movements_samples.begin (); - i != movements_samples.end (); - ++i) { - movements.push_back (Evoral::RangeMove (i->from, i->length, i->to)); - } - /* move panner automation */ boost::shared_ptr pannable = _track.pannable (); Evoral::ControlSet::Controls& c (pannable->controls ()); @@ -1393,22 +1385,17 @@ DiskReader::playlist_ranges_moved (list > const& } } /* move processor automation */ - _track.foreach_processor (boost::bind (&DiskReader::move_processor_automation, this, _1, movements_samples)); + _track.foreach_processor (boost::bind (&DiskReader::move_processor_automation, this, _1, movements)); } void -DiskReader::move_processor_automation (boost::weak_ptr p, list > const& movements_samples) +DiskReader::move_processor_automation (boost::weak_ptr p, list const& movements) { boost::shared_ptr processor (p.lock ()); if (!processor) { return; } - list > movements; - for (list >::const_iterator i = movements_samples.begin (); i != movements_samples.end (); ++i) { - movements.push_back (Evoral::RangeMove (i->from, i->length, i->to)); - } - set const a = processor->what_can_be_automated (); for (set::const_iterator i = a.begin (); i != a.end (); ++i) { @@ -1480,18 +1467,19 @@ DiskReader::get_midi_playback (MidiBuffer& dst, samplepos_t start_sample, sample if (loc) { /* Evoral::Range has inclusive range semantics. Ugh. Hence the -1 */ - const Evoral::Range loop_range (loc->start (), loc->end () - 1); - samplepos_t effective_start = start_sample; - samplecnt_t cnt = nframes; - sampleoffset_t offset = 0; + const Temporal::Range loop_range (loc->start (), loc->end ()); + samplepos_t effective_start = start_sample; + samplecnt_t cnt = nframes; + sampleoffset_t offset = 0; + const samplepos_t loop_end = loc->end_sample(); DEBUG_TRACE (DEBUG::MidiDiskIO, string_compose ("LOOP read, loop is %1..%2 range is %3..%4 nf %5\n", loc->start (), loc->end (), start_sample, end_sample, nframes)); do { samplepos_t effective_end; - effective_start = loop_range.squish (effective_start); - effective_end = min (effective_start + cnt, loc->end ()); + effective_start = loop_range.squish (timepos_t (effective_start)).samples(); + effective_end = min (effective_start + cnt, loop_end); assert (effective_end > effective_start); const samplecnt_t this_read = effective_end - effective_start; @@ -1739,8 +1727,8 @@ DiskReader::Declicker::run (Sample* buf, samplepos_t read_start, samplepos_t rea * see also DiskReader::maybe_xfade_loop() */ - switch (Evoral::coverage (fade_start, fade_end, read_start, read_end)) { - case Evoral::OverlapInternal: + switch (Temporal::coverage_exclusive_ends (fade_start, fade_end, read_start, read_end)) { + case Temporal::OverlapInternal: /* note: start and end points cannot coincide (see evoral/Range.h) * * read range is entirely within fade range @@ -1750,7 +1738,7 @@ DiskReader::Declicker::run (Sample* buf, samplepos_t read_start, samplepos_t rea n = read_end - read_start; break; - case Evoral::OverlapExternal: + case Temporal::OverlapExternal: /* read range extends on either side of fade range * * External allows coincidental start & end points, so check for that @@ -1767,14 +1755,14 @@ DiskReader::Declicker::run (Sample* buf, samplepos_t read_start, samplepos_t rea } break; - case Evoral::OverlapStart: + case Temporal::OverlapStart: /* read range starts before and ends within fade or at same end as fade */ n = fade_end - read_start; vo = 0; bo = fade_start - read_start; break; - case Evoral::OverlapEnd: + case Temporal::OverlapEnd: /* read range starts within fade range, but possibly at it's end, so check */ if (read_start == fade_end) { /* nothing to do */ @@ -1785,7 +1773,7 @@ DiskReader::Declicker::run (Sample* buf, samplepos_t read_start, samplepos_t rea n = fade_end - read_start; break; - case Evoral::OverlapNone: + case Temporal::OverlapNone: /* no overlap ... nothing to do */ return; } @@ -1818,8 +1806,8 @@ DiskReader::maybe_xfade_loop (Sample* buf, samplepos_t read_start, samplepos_t r * see also DiskReader::Declicker::run() */ - switch (Evoral::coverage (fade_start, fade_end, read_start, read_end)) { - case Evoral::OverlapInternal: + switch (Temporal::coverage_exclusive_ends (fade_start, fade_end, read_start, read_end)) { + case Temporal::OverlapInternal: /* note: start and end points cannot coincide (see evoral/Range.h) * * read range is entirely within fade range @@ -1829,7 +1817,7 @@ DiskReader::maybe_xfade_loop (Sample* buf, samplepos_t read_start, samplepos_t r n = read_end - read_start; break; - case Evoral::OverlapExternal: + case Temporal::OverlapExternal: /* read range extends on either side of fade range * * External allows coincidental start & end points, so check for that @@ -1846,14 +1834,14 @@ DiskReader::maybe_xfade_loop (Sample* buf, samplepos_t read_start, samplepos_t r } break; - case Evoral::OverlapStart: + case Temporal::OverlapStart: /* read range starts before and ends within fade or at same end as fade */ n = read_end - fade_start; vo = 0; bo = fade_start - read_start; break; - case Evoral::OverlapEnd: + case Temporal::OverlapEnd: /* read range starts within fade range, but possibly at it's end, so check */ if (read_start == fade_end) { /* nothing to do */ @@ -1864,7 +1852,7 @@ DiskReader::maybe_xfade_loop (Sample* buf, samplepos_t read_start, samplepos_t r n = fade_end - read_start; break; - case Evoral::OverlapNone: + case Temporal::OverlapNone: /* no overlap ... nothing to do */ return; } @@ -1912,8 +1900,8 @@ void DiskReader::reset_loop_declick (Location* loc, samplecnt_t sr) { if (loc) { - loop_declick_in.reset (loc->start (), loc->end (), true, sr); - loop_declick_out.reset (loc->start (), loc->end (), false, sr); + loop_declick_in.reset (loc->start_sample (), loc->end_sample (), true, sr); + loop_declick_out.reset (loc->start_sample (), loc->end_sample (), false, sr); } else { loop_declick_in.reset (0, 0, true, sr); loop_declick_out.reset (0, 0, false, sr); @@ -1946,6 +1934,8 @@ DiskReader::setup_preloop_buffer () Location* loc = _loop_location; boost::scoped_array mix_buf (new Sample[loop_fade_length]); boost::scoped_array gain_buf (new Sample[loop_fade_length]); + const timepos_t read_start = timepos_t (loc->start_sample() - loop_declick_out.fade_length); + const timecnt_t read_cnt = timecnt_t (loop_declick_out.fade_length); uint32_t channel = 0; @@ -1955,7 +1945,7 @@ DiskReader::setup_preloop_buffer () rci->resize_preloop (loop_fade_length); if (loc->start () > loop_fade_length) { - audio_playlist ()->read (rci->pre_loop_buffer, mix_buf.get (), gain_buf.get (), loc->start () - loop_declick_out.fade_length, loop_declick_out.fade_length, channel); + audio_playlist ()->read (rci->pre_loop_buffer, mix_buf.get (), gain_buf.get (), read_start, read_cnt, channel); } else { memset (rci->pre_loop_buffer, 0, sizeof (Sample) * loop_fade_length); } diff --git a/libs/ardour/disk_writer.cc b/libs/ardour/disk_writer.cc index 39ef292946..ebb997be55 100644 --- a/libs/ardour/disk_writer.cc +++ b/libs/ardour/disk_writer.cc @@ -169,12 +169,13 @@ DiskWriter::check_record_status (samplepos_t transport_sample, double speed, boo Location* loc; if (_session.config.get_punch_in () && 0 != (loc = _session.locations()->auto_punch_location ())) { - _capture_start_sample = loc->start (); + _capture_start_sample = loc->start_sample (); } else if (_loop_location) { - _capture_start_sample = _loop_location->start (); + _capture_start_sample = _loop_location->start_sample (); if (_last_possibly_recording & transport_rolling) { _accumulated_capture_offset = _playback_offset + transport_sample - _session.transport_sample (); // + rec_offset; } + } else { _capture_start_sample = _session.transport_sample (); } @@ -191,7 +192,7 @@ DiskWriter::check_record_status (samplepos_t transport_sample, double speed, boo * We should allow to move it or at least allow to disable punch-out * while rolling.. */ - _last_recordable_sample = loc->end (); + _last_recordable_sample = loc->end_sample (); if (_alignment_style == ExistingMaterial) { _last_recordable_sample += _capture_offset + _playback_offset; } @@ -234,14 +235,14 @@ DiskWriter::check_record_status (samplepos_t transport_sample, double speed, boo } void -DiskWriter::calculate_record_range (Evoral::OverlapType ot, samplepos_t transport_sample, samplecnt_t nframes, samplecnt_t & rec_nframes, samplecnt_t & rec_offset) +DiskWriter::calculate_record_range (Temporal::OverlapType ot, samplepos_t transport_sample, samplecnt_t nframes, samplecnt_t & rec_nframes, samplecnt_t & rec_offset) { switch (ot) { - case Evoral::OverlapNone: + case Temporal::OverlapNone: rec_nframes = 0; break; - case Evoral::OverlapInternal: + case Temporal::OverlapInternal: /* ---------- recrange * |---| transrange */ @@ -249,7 +250,7 @@ DiskWriter::calculate_record_range (Evoral::OverlapType ot, samplepos_t transpor rec_offset = 0; break; - case Evoral::OverlapStart: + case Temporal::OverlapStart: /* |--------| recrange * -----| transrange */ @@ -259,7 +260,7 @@ DiskWriter::calculate_record_range (Evoral::OverlapType ot, samplepos_t transpor } break; - case Evoral::OverlapEnd: + case Temporal::OverlapEnd: /* |--------| recrange * |-------- transrange */ @@ -267,7 +268,7 @@ DiskWriter::calculate_record_range (Evoral::OverlapType ot, samplepos_t transpor rec_offset = 0; break; - case Evoral::OverlapExternal: + case Temporal::OverlapExternal: /* |--------| recrange * -------------- transrange */ @@ -394,7 +395,8 @@ void DiskWriter::non_realtime_locate (samplepos_t position) { if (_midi_write_source) { - _midi_write_source->set_natural_position (position); +#warning NUTEMPO maybe fixme perhaps take sources time domain into account here e.g. beats + _midi_write_source->set_natural_position (timepos_t (position)); } DiskIOProcessor::non_realtime_locate (position); @@ -430,14 +432,14 @@ DiskWriter::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp bool re = record_enabled (); bool punch_in = _session.config.get_punch_in () && _session.locations()->auto_punch_location (); bool can_record = _session.actively_recording (); - can_record |= speed != 0 && _session.get_record_enabled () && punch_in && _session.transport_sample () <= _session.locations()->auto_punch_location ()->start (); + can_record |= speed != 0 && _session.get_record_enabled () && punch_in && _session.transport_sample () <= _session.locations()->auto_punch_location ()->start_sample (); _need_butler = false; - const Location* const loop_loc = _loop_location; - samplepos_t loop_start = 0; - samplepos_t loop_end = 0; - samplepos_t loop_length = 0; + const Location* const loop_loc = _loop_location; + timepos_t loop_start; + timepos_t loop_end; + timecnt_t loop_length; if (_transport_looped && _capture_captured == 0) { _transport_looped = false; @@ -446,9 +448,9 @@ DiskWriter::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp if (loop_loc) { get_location_times (loop_loc, &loop_start, &loop_end, &loop_length); - if (_was_recording && _transport_looped && _capture_captured >= loop_length) { - samplecnt_t remain = _capture_captured - loop_length; - _capture_captured = loop_length; + if (_was_recording && _transport_looped && _capture_captured >= loop_length.samples()) { + samplecnt_t remain = _capture_captured - loop_length.samples(); + _capture_captured = loop_length.samples(); loop (_transport_loop_sample); _capture_captured = remain; } @@ -481,7 +483,7 @@ DiskWriter::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp if (nominally_recording || (re && _was_recording && _session.get_record_enabled() && punch_in)) { - Evoral::OverlapType ot = Evoral::coverage (_first_recordable_sample, _last_recordable_sample, start_sample, end_sample); + Temporal::OverlapType ot = Temporal::coverage_exclusive_ends (_first_recordable_sample, _last_recordable_sample, start_sample, end_sample); // XXX should this be transport_sample + nframes - 1 ? coverage() expects its parameter ranges to include their end points // XXX also, first_recordable_sample & last_recordable_sample may both be == max_samplepos: coverage() will return OverlapNone in that case. Is thak OK? calculate_record_range (ot, start_sample, nframes, rec_nframes, rec_offset); @@ -498,9 +500,10 @@ DiskWriter::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp at the loop start and can handle time wrapping around. Otherwise, start the source right now as usual. */ - _capture_captured = start_sample - loop_start + rec_offset; - _capture_start_sample = loop_start; - _first_recordable_sample = loop_start; + + _capture_captured = start_sample - loop_start.samples() + rec_offset; + _capture_start_sample = loop_start.samples(); + _first_recordable_sample = loop_start.samples(); if (_alignment_style == ExistingMaterial) { _capture_captured -= _playback_offset + _capture_offset; @@ -521,7 +524,7 @@ DiskWriter::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp if (_midi_write_source) { assert (_capture_start_sample); - _midi_write_source->mark_write_starting_now (_capture_start_sample.value (), _capture_captured, loop_length); + _midi_write_source->mark_write_starting_now (_capture_start_sample, _capture_captured, loop_length.samples()); } g_atomic_int_set (&_samples_pending_write, 0); @@ -629,7 +632,7 @@ DiskWriter::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp reconstruct their actual time; future clever MIDI looping should probably be implemented in the source instead of here. */ - const samplecnt_t loop_offset = g_atomic_int_get (&_num_captured_loops) * loop_length; + const samplecnt_t loop_offset = g_atomic_int_get (&_num_captured_loops) * loop_length.samples(); const samplepos_t event_time = start_sample + loop_offset - _accumulated_capture_offset + ev.time(); if (event_time < 0 || event_time < _first_recordable_sample) { /* Event out of range, skip */ @@ -743,11 +746,11 @@ DiskWriter::finish_capture (boost::shared_ptr c) _xruns.clear (); if (_loop_location) { - samplepos_t loop_start = 0; - samplepos_t loop_end = 0; - samplepos_t loop_length = 0; + timepos_t loop_start; + timepos_t loop_end; + timecnt_t loop_length; get_location_times (_loop_location, &loop_start, &loop_end, &loop_length); - ci->loop_offset = g_atomic_int_get (&_num_captured_loops) * loop_length; + ci->loop_offset = g_atomic_int_get (&_num_captured_loops) * loop_length.samples(); } else { ci->loop_offset = 0; } @@ -1021,7 +1024,7 @@ DiskWriter::do_flush (RunContext ctxt, bool force_flush) if ((total > _chunk_samples) || force_flush) { Source::Lock lm(_midi_write_source->mutex()); - if (_midi_write_source->midi_write (lm, *_midi_buf, get_capture_start_sample (0), to_write) != to_write) { + if (_midi_write_source->midi_write (lm, *_midi_buf, timepos_t (get_capture_start_sample (0)), timecnt_t (to_write)) != to_write) { error << string_compose(_("MidiDiskstream %1: cannot write to disk"), id()) << endmsg; return -1; } @@ -1221,7 +1224,7 @@ DiskWriter::transport_stopped_wallclock (struct tm& when, time_t twhen, bool abo Analyser::queue_source_for_analysis (as, true); } - DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("newly captured source %1 length %2\n", as->path(), as->length (0))); + DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("newly captured source %1 length %2\n", as->path(), as->length ())); } if (_midi_write_source) { @@ -1238,7 +1241,7 @@ DiskWriter::transport_stopped_wallclock (struct tm& when, time_t twhen, bool abo if (_midi_write_source) { - if (_midi_write_source->length (capture_info.front()->start) == 0) { + if (_midi_write_source->empty()) { /* No data was recorded, so this capture will effectively be aborted; do the same as we do for an explicit abort. @@ -1260,27 +1263,17 @@ DiskWriter::transport_stopped_wallclock (struct tm& when, time_t twhen, bool abo midi_srcs.push_back (_midi_write_source); - _midi_write_source->set_natural_position (capture_info.front()->start); - _midi_write_source->set_captured_for (_track.name ()); + _midi_write_source->set_natural_position (timepos_t (capture_info.front()->start)); + _midi_write_source->set_captured_for (_track.name()); Glib::DateTime tm (Glib::DateTime::create_now_local (mktime (&when))); _midi_write_source->set_take_id (tm.format ("%F %H.%M.%S")); - /* set length in beats to entire capture length */ - - - Temporal::Beats total_capture_beats; - for (vector::iterator ci = capture_info.begin(); ci != capture_info.end(); ++ci) { - BeatsSamplesConverter converter (_session.tempo_map(), (*ci)->start); - total_capture_beats += converter.from ((*ci)->samples); - } - _midi_write_source->set_length_beats (total_capture_beats); - /* flush to disk: this step differs from the audio path, where all the data is already on disk. */ - _midi_write_source->mark_midi_streaming_write_completed (source_lock, Evoral::Sequence::ResolveStuckNotes, total_capture_beats); + _midi_write_source->mark_midi_streaming_write_completed (source_lock, Evoral::Sequence::ResolveStuckNotes, timecnt_t (total_capture, timepos_t (capture_info.front()->start)).beats()); } _last_capture_sources.insert (_last_capture_sources.end(), audio_srcs.begin(), audio_srcs.end()); diff --git a/libs/ardour/ebur128_analysis.cc b/libs/ardour/ebur128_analysis.cc index a8bc477994..d419f91ba5 100644 --- a/libs/ardour/ebur128_analysis.cc +++ b/libs/ardour/ebur128_analysis.cc @@ -42,7 +42,7 @@ EBUr128Analysis::~EBUr128Analysis() } int -EBUr128Analysis::run (Readable* src) +EBUr128Analysis::run (AudioReadable* src) { int ret = -1; bool done = false; diff --git a/libs/ardour/enums.cc b/libs/ardour/enums.cc index cf32e93db2..8090ad0110 100644 --- a/libs/ardour/enums.cc +++ b/libs/ardour/enums.cc @@ -29,8 +29,6 @@ #include "pbd/enumwriter.h" #include "midi++/types.h" -#include "evoral/Range.h" // shouldn't Evoral have its own enum registration? - #include "ardour/delivery.h" #include "ardour/disk_io.h" #include "ardour/export_channel.h" @@ -146,7 +144,6 @@ setup_enum_writer () ScreenSaverMode _ScreenSaverMode; Session::PostTransportWork _Session_PostTransportWork; MTC_Status _MIDI_MTC_Status; - Evoral::OverlapType _OverlapType; BufferingPreset _BufferingPreset; AutoReturnTarget _AutoReturnTarget; PresentationInfo::Flag _PresentationInfo_Flag; @@ -743,13 +740,6 @@ setup_enum_writer () REGISTER_ENUM(MusicTime); REGISTER(_PositionLockStyle); - REGISTER_ENUM (Evoral::OverlapNone); - REGISTER_ENUM (Evoral::OverlapInternal); - REGISTER_ENUM (Evoral::OverlapStart); - REGISTER_ENUM (Evoral::OverlapEnd); - REGISTER_ENUM (Evoral::OverlapExternal); - REGISTER(_OverlapType); - REGISTER_ENUM (Small); REGISTER_ENUM (Medium); REGISTER_ENUM (Large); diff --git a/libs/ardour/export_channel.cc b/libs/ardour/export_channel.cc index a6fb193324..85dcf7c46a 100644 --- a/libs/ardour/export_channel.cc +++ b/libs/ardour/export_channel.cc @@ -174,7 +174,7 @@ RegionExportChannelFactory::RegionExportChannelFactory (Session * session, Audio , type (type) , samples_per_cycle (session->engine().samples_per_cycle ()) , buffers_up_to_date (false) - , region_start (region.position()) + , region_start (region.position_sample()) , position (region_start) { switch (type) { diff --git a/libs/ardour/export_handler.cc b/libs/ardour/export_handler.cc index 033fdd8fde..f4a54391ee 100644 --- a/libs/ardour/export_handler.cc +++ b/libs/ardour/export_handler.cc @@ -598,7 +598,7 @@ ExportHandler::export_cd_marker_file (ExportTimespanPtr timespan, ExportFormatSp if ((*i)->is_mark()) { /* Index within track */ - status.index_position = (*i)->start() - timespan->get_start(); + status.index_position = (*i)->start_sample() - timespan->get_start(); (this->*index_func) (status); } @@ -608,7 +608,7 @@ ExportHandler::export_cd_marker_file (ExportTimespanPtr timespan, ExportFormatSp /* A track, defined by a cd range marker or a cd location marker outside of a cd range */ status.track_position = last_end_time - timespan->get_start(); - status.track_start_sample = (*i)->start() - timespan->get_start(); // everything before this is the pregap + status.track_start_sample = (*i)->start_sample() - timespan->get_start(); // everything before this is the pregap status.track_duration = 0; if ((*i)->is_mark()) { @@ -617,9 +617,9 @@ ExportHandler::export_cd_marker_file (ExportTimespanPtr timespan, ExportFormatSp ++nexti; if (nexti != temp.end()) { - status.track_duration = (*nexti)->start() - last_end_time; + status.track_duration = (*nexti)->start_sample() - last_end_time; - last_end_time = (*nexti)->start(); + last_end_time = (*nexti)->start_sample(); } else { // this was the last marker, use timespan end status.track_duration = timespan->get_end() - last_end_time; @@ -628,9 +628,9 @@ ExportHandler::export_cd_marker_file (ExportTimespanPtr timespan, ExportFormatSp } } else { // range - status.track_duration = (*i)->end() - last_end_time; + status.track_duration = (*i)->end_sample() - last_end_time; - last_end_time = (*i)->end(); + last_end_time = (*i)->end_sample(); } (this->*track_func) (status); diff --git a/libs/ardour/export_profile_manager.cc b/libs/ardour/export_profile_manager.cc index 09c23cac19..512f692c1c 100644 --- a/libs/ardour/export_profile_manager.cc +++ b/libs/ardour/export_profile_manager.cc @@ -363,7 +363,7 @@ ExportProfileManager::set_selection_range (samplepos_t start, samplepos_t end) if (start || end) { selection_range.reset (new Location (session)); selection_range->set_name (_("Selection")); - selection_range->set (start, end); + selection_range->set (timepos_t (start), timepos_t (end)); } else { selection_range.reset(); } @@ -380,7 +380,7 @@ ExportProfileManager::set_single_range (samplepos_t start, samplepos_t end, stri single_range.reset (new Location (session)); single_range->set_name (name); - single_range->set (start, end); + single_range->set (timepos_t (start), timepos_t (end)); update_ranges (); @@ -415,7 +415,7 @@ ExportProfileManager::init_timespans (XMLNodeList nodes) ExportTimespanPtr timespan = handler->add_timespan(); timespan->set_name (session_range->name()); timespan->set_range_id (session_range->id().to_s()); - timespan->set_range (session_range->start(), session_range->end()); + timespan->set_range (session_range->start_sample(), session_range->end_sample()); state->timespans->push_back (timespan); return false; } @@ -450,7 +450,7 @@ ExportProfileManager::deserialize_timespan (XMLNode & root) ExportTimespanPtr timespan = handler->add_timespan(); timespan->set_name (location->name()); timespan->set_range_id (location->id().to_s()); - timespan->set_range (location->start(), location->end()); + timespan->set_range (location->start_sample(), location->end_sample()); state->timespans->push_back (timespan); } diff --git a/libs/ardour/filter.cc b/libs/ardour/filter.cc index 00e599b4e1..5067e5013d 100644 --- a/libs/ardour/filter.cc +++ b/libs/ardour/filter.cc @@ -43,9 +43,10 @@ int Filter::make_new_sources (boost::shared_ptr region, SourceList& nsrcs, std::string suffix, bool use_session_sample_rate) { vector names = region->master_source_names(); - assert (region->n_channels() <= names.size()); + const SourceList::size_type nsrc = region->sources().size(); + assert (nsrc <= names.size()); - for (uint32_t i = 0; i < region->n_channels(); ++i) { + for (SourceList::size_type i = 0; i < nsrc; ++i) { string name = PBD::basename_nosuffix (names[i]); @@ -62,7 +63,7 @@ Filter::make_new_sources (boost::shared_ptr region, SourceList& nsrcs, s const string path = (region->data_type() == DataType::MIDI) ? session.new_midi_source_path (name) - : session.new_audio_source_path (name, region->n_channels(), i, false); + : session.new_audio_source_path (name, nsrc, i, false); if (path.empty()) { error << string_compose (_("filter: error creating name for new file based on %1"), region->name()) @@ -120,7 +121,7 @@ Filter::finish (boost::shared_ptr region, SourceList& nsrcs, string regi boost::shared_ptr smfs = boost::dynamic_pointer_cast(*si); if (smfs) { - smfs->set_natural_position (region->position_sample()); + smfs->set_natural_position (region->nt_position()); smfs->flush (); } @@ -138,7 +139,7 @@ Filter::finish (boost::shared_ptr region, SourceList& nsrcs, string regi PropertyList plist; - plist.add (Properties::start, 0); + plist.add (Properties::start, std::numeric_limits::min()); plist.add (Properties::length, region->nt_length()); plist.add (Properties::name, region_name); plist.add (Properties::whole_file, true); diff --git a/libs/ardour/gain_control.cc b/libs/ardour/gain_control.cc index ab8ecf82ee..807170fd97 100644 --- a/libs/ardour/gain_control.cc +++ b/libs/ardour/gain_control.cc @@ -63,7 +63,7 @@ static boost::shared_ptr automation_list_new (Evoral::Parameter case BusSendLevel: /* fallthrough */ case TrimAutomation: - return boost::shared_ptr (new AutomationList (param)); + return boost::shared_ptr (new AutomationList (param, Temporal::AudioTime)); case MainOutVolume: /* not automatable */ break; @@ -112,10 +112,10 @@ bool GainControl::get_masters_curve_locked (samplepos_t start, samplepos_t end, float* vec, samplecnt_t veclen) const { if (_masters.empty()) { - return list()->curve().rt_safe_get_vector (start, end, vec, veclen); + return list()->curve().rt_safe_get_vector (timepos_t (start), timepos_t (end), vec, veclen); } for (samplecnt_t i = 0; i < veclen; ++i) { vec[i] = 1.f; } - return SlavableAutomationControl::masters_curve_multiply (start, end, vec, veclen); + return SlavableAutomationControl::masters_curve_multiply (timepos_t (start), timepos_t (end), vec, veclen); } diff --git a/libs/ardour/globals.cc b/libs/ardour/globals.cc index facee2f95f..ce509c062d 100644 --- a/libs/ardour/globals.cc +++ b/libs/ardour/globals.cc @@ -539,6 +539,8 @@ ARDOUR::init (bool try_optimization, const char* localedir, bool with_gui) if (!PBD::init ()) return false; + Temporal::init (); + #if ENABLE_NLS (void)bindtextdomain (PACKAGE, localedir); (void)bind_textdomain_codeset (PACKAGE, "UTF-8"); diff --git a/libs/ardour/import.cc b/libs/ardour/import.cc index 7852ac0dfc..c67411aa0e 100644 --- a/libs/ardour/import.cc +++ b/libs/ardour/import.cc @@ -231,7 +231,7 @@ create_mono_sources_for_writing (const vector& new_paths, boost::shared_ptr afs; if ((afs = boost::dynamic_pointer_cast(source)) != 0) { - afs->set_natural_position (natural_position); + afs->set_natural_position (timepos_t (natural_position)); } } return true; @@ -462,8 +462,7 @@ write_midi_data_to_new_files (Evoral::SMF* source, ImportStatus& status, const samplepos_t pos = 0; const Temporal::Beats length_beats = Temporal::Beats::ticks_at_rate(t, source->ppqn()); - BeatsSamplesConverter converter(smfs->session().tempo_map(), pos); - smfs->update_length(pos + converter.to(length_beats.round_up_to_beat())); + smfs->update_length (timecnt_t (length_beats.round_up_to_beat(), timepos_t(Temporal::BeatTime))); smfs->mark_streaming_write_completed (source_lock); if (status.cancel) { @@ -618,7 +617,7 @@ Session::import_files (ImportStatus& status) for (Sources::iterator x = all_new_sources.begin(); x != all_new_sources.end(); ) { if ((afs = boost::dynamic_pointer_cast(*x)) != 0) { - afs->update_header((*x)->natural_position(), *now, xnow); + afs->update_header((*x)->natural_position().samples(), *now, xnow); afs->done_with_peakfile_writes (); /* now that there is data there, requeue the file for analysis */ diff --git a/libs/ardour/import_pt.cc b/libs/ardour/import_pt.cc index 30fcc4c8d3..b029b017df 100644 --- a/libs/ardour/import_pt.cc +++ b/libs/ardour/import_pt.cc @@ -75,7 +75,7 @@ struct PlaylistState { }; bool -Session::import_sndfile_as_region (string path, SrcQuality quality, samplepos_t& pos, SourceList& sources, ImportStatus& status, uint32_t current, uint32_t total) +Session::import_sndfile_as_region (string path, SrcQuality quality, timepos_t& pos, SourceList& sources, ImportStatus& status, uint32_t current, uint32_t total) { /* Import the source */ status.paths.clear(); @@ -113,7 +113,7 @@ Session::import_sndfile_as_region (string path, SrcQuality quality, samplepos_t& string region_name; bool use_timestamp; - use_timestamp = (pos == -1); + use_timestamp = (pos == timepos_t::max (Temporal::AudioTime)); /* take all the sources we have and package them up as a region */ @@ -127,8 +127,8 @@ Session::import_sndfile_as_region (string path, SrcQuality quality, samplepos_t& PropertyList plist; - plist.add (ARDOUR::Properties::start, 0); - plist.add (ARDOUR::Properties::length, sources[0]->length (pos)); + plist.add (ARDOUR::Properties::start, timepos_t (0)); + plist.add (ARDOUR::Properties::length, timecnt_t (sources[0]->length (), pos)); plist.add (ARDOUR::Properties::name, region_name); plist.add (ARDOUR::Properties::layer, 0); plist.add (ARDOUR::Properties::whole_file, true); @@ -164,11 +164,11 @@ Session::import_sndfile_as_region (string path, SrcQuality quality, samplepos_t& if (as->natural_position() != 0) { pos = as->natural_position(); } else { - pos = 0; + pos = timepos_t (pos.time_domain ()); } } else { /* should really get first position in MIDI file, but for now, use 0 */ - pos = 0; + pos = timepos_t (pos.time_domain()); } } } @@ -187,7 +187,8 @@ Session::import_pt_sources (PTFFormat& ptf, ImportStatus& status) string fullpath; bool ok = false; bool onefailed = false; - samplepos_t pos = -1; + timepos_t pos = timepos_t::max (Temporal::AudioTime); + uint32_t srate = sample_rate (); vector::const_iterator w; uint32_t wth = 0; @@ -376,12 +377,42 @@ Session::import_pt_rest (PTFFormat& ptf) /* Matched a ptf active region to an ardour region */ boost::shared_ptr r = RegionFactory::region_by_id (p->id); - DEBUG_TRACE (DEBUG::FileUtils, string_compose ("\twav(%1) reg(%2) tr(%3)\n", a->reg.wave.filename.c_str (), a->reg.index, a->index)); + vector::iterator lookuptr = usedtracks.begin (); + vector::iterator found; + if ((found = std::find (lookuptr, usedtracks.end (), utr)) != usedtracks.end ()) { + DEBUG_TRACE (DEBUG::FileUtils, string_compose ("\twav(%1) reg(%2) ptf_tr(%3) ard_tr(%4)\n", a->reg.wave.filename.c_str (), a->reg.index, found->index1, found->index2)); - /* Use existing playlists */ - boost::shared_ptr playlist = playlists[a->index].playlist; - boost::shared_ptr copy (RegionFactory::create (r, true)); - playlist->add_region (copy, a->reg.startpos); + /* Use existing track if possible */ + existing_track = get_nth_audio_track (found->index2 + 1); + if (!existing_track) { + list > at (new_audio_track (1, 2, 0, 1, a->name.c_str(), PresentationInfo::max_order, Normal)); + if (at.empty ()) { + return; + } + existing_track = at.back (); + } + /* Put on existing track */ + boost::shared_ptr playlist = existing_track->playlist (); + boost::shared_ptr copy (RegionFactory::create (r, true)); + playlist->clear_changes (); + playlist->add_region (copy, timepos_t (a->reg.startpos)); + //add_command (new StatefulDiffCommand (playlist)); + } else { + /* Put on a new track */ + DEBUG_TRACE (DEBUG::FileUtils, string_compose ("\twav(%1) reg(%2) new_tr(%3)\n", a->reg.wave.filename.c_str (), a->reg.index, nth)); + list > at (new_audio_track (1, 2, 0, 1, a->name.c_str(), PresentationInfo::max_order, Normal)); + if (at.empty ()) { + return; + } + existing_track = at.back (); + boost::shared_ptr playlist = existing_track->playlist(); + boost::shared_ptr copy (RegionFactory::create (r, true)); + playlist->clear_changes (); + playlist->add_region (copy, timepos_t (a->reg.startpos)); + //add_command (new StatefulDiffCommand (playlist)); + nth++; + usedtracks.push_back (utr); + } } } } @@ -442,9 +473,9 @@ no_audio_tracks: plist.add (ARDOUR::Properties::name, PBD::basename_nosuffix (src->name ())); //printf(" : %d - trackname: (%s)\n", a->index, src->name ().c_str ()); boost::shared_ptr region = (RegionFactory::create (src, plist)); - /* sets beat position */ - region->set_position (pos.sample, pos.division); - midi_track->playlist ()->add_region (region, pos.sample, 1.0, false, pos.division); + /* sets position */ + region->set_position (timepos_t (pos.sample)); + midi_track->playlist ()->add_region (region, timepos_t (pos.sample), 1.0, false); boost::shared_ptr mr = boost::dynamic_pointer_cast(region); boost::shared_ptr mm = mr->midi_source (0)->model (); @@ -461,6 +492,6 @@ no_audio_tracks: mm->apply_command (this, midicmd); boost::shared_ptr copy (RegionFactory::create (mr, true)); playlist->clear_changes (); - playlist->add_region (copy, f); + playlist->add_region (copy, timepos_t (f)); } } diff --git a/libs/ardour/location.cc b/libs/ardour/location.cc index 3f4040c23f..7a5921ba5d 100644 --- a/libs/ardour/location.cc +++ b/libs/ardour/location.cc @@ -53,6 +53,7 @@ namespace PBD { using namespace std; using namespace ARDOUR; using namespace PBD; +using namespace Temporal; PBD::Signal0 Location::scene_changed; PBD::Signal1 Location::name_changed; @@ -60,39 +61,32 @@ PBD::Signal1 Location::end_changed; PBD::Signal1 Location::start_changed; PBD::Signal1 Location::flags_changed; PBD::Signal1 Location::lock_changed; -PBD::Signal1 Location::position_lock_style_changed; PBD::Signal1 Location::changed; Location::Location (Session& s) : SessionHandleRef (s) - , _start (0) - , _start_beat (0.0) - , _end (0) - , _end_beat (0.0) , _flags (Flags (0)) , _locked (false) - , _position_lock_style (AudioTime) , _timestamp (time (0)) { - assert (_start >= 0); - assert (_end >= 0); } /** Construct a new Location, giving it the position lock style determined by glue-new-markers-to-bars-and-beats */ -Location::Location (Session& s, samplepos_t sample_start, samplepos_t sample_end, const std::string &name, Flags bits, const uint32_t sub_num) +Location::Location (Session& s, timepos_t const & start, timepos_t const & end, const std::string &name, Flags bits) : SessionHandleRef (s) , _name (name) - , _start (sample_start) - , _end (sample_end) + , _start (start) + , _end (end) , _flags (bits) , _locked (false) - , _position_lock_style (s.config.get_glue_new_markers_to_bars_and_beats() ? MusicTime : AudioTime) , _timestamp (time (0)) { - recompute_beat_from_samples (sub_num); - - assert (_start >= 0); - assert (_end >= 0); +#warning NUTEMPO FIXME drop this and ensure that timepos start/end use correct domain in caller for this constructor + if (s.config.get_glue_new_markers_to_bars_and_beats()) { + set_position_time_domain (Temporal::BeatTime); + } else { + set_position_time_domain (Temporal::AudioTime); + } } Location::Location (const Location& other) @@ -100,39 +94,32 @@ Location::Location (const Location& other) , StatefulDestructible() , _name (other._name) , _start (other._start) - , _start_beat (other._start_beat) , _end (other._end) - , _end_beat (other._end_beat) , _flags (other._flags) - , _position_lock_style (other._position_lock_style) , _timestamp (time (0)) { /* copy is not locked even if original was */ _locked = false; - assert (_start >= 0); - assert (_end >= 0); - /* scene change is NOT COPIED */ } Location::Location (Session& s, const XMLNode& node) : SessionHandleRef (s) , _flags (Flags (0)) - , _position_lock_style (AudioTime) , _timestamp (time (0)) { - /* Note: _position_lock_style is initialised above in case set_state doesn't set it - (for 2.X session file compatibility). - */ + //_start.set_time_domain (AudioTime); + //_end.set_time_domain (AudioTime); + + /* Note: _position_time_domain is initialised above in case set_state + * doesn't set it + */ if (set_state (node, Stateful::loading_state_version)) { throw failed_constructor (); } - - assert (_start >= 0); - assert (_end >= 0); } bool @@ -141,10 +128,7 @@ Location::operator== (const Location& other) if (_name != other._name || _start != other._start || _end != other._end || - _start_beat != other._start_beat || - _end_beat != other._end_beat || - _flags != other._flags || - _position_lock_style != other._position_lock_style) { + _flags != other._flags) { return false; } return true; @@ -159,11 +143,8 @@ Location::operator= (const Location& other) _name = other._name; _start = other._start; - _start_beat = other._start_beat; _end = other._end; - _end_beat = other._end_beat; _flags = other._flags; - _position_lock_style = other._position_lock_style; /* XXX need to copy scene change */ @@ -173,9 +154,6 @@ Location::operator= (const Location& other) /* "changed" not emitted on purpose */ - assert (_start >= 0); - assert (_end >= 0); - return this; } @@ -194,14 +172,10 @@ Location::set_name (const std::string& str) /** Set start position. * @param s New start. * @param force true to force setting, even if the given new start is after the current end. - * @param allow_beat_recompute True to recompute BEAT start time from the new given start time. */ int -Location::set_start (samplepos_t s, bool force, bool allow_beat_recompute, const uint32_t sub_num) +Location::set_start (Temporal::timepos_t const & s, bool force) { - if (s < 0) { - return -1; - } if (_locked) { return -1; @@ -217,9 +191,6 @@ Location::set_start (samplepos_t s, bool force, bool allow_beat_recompute, const if (_start != s) { _start = s; _end = s; - if (allow_beat_recompute) { - recompute_beat_from_samples (sub_num); - } start_changed (this); /* EMIT SIGNAL */ StartChanged (); /* EMIT SIGNAL */ @@ -235,51 +206,42 @@ Location::set_start (samplepos_t s, bool force, bool allow_beat_recompute, const scene_changed (); /* EMIT SIGNAL */ } - assert (_start >= 0); - assert (_end >= 0); + assert (s.zero() || s.positive()); return 0; } else if (!force) { /* range locations must exceed a minimum duration */ - if (_end - s < Config->get_range_location_minimum()) { + if (s.distance (_end) < Config->get_range_location_minimum()) { return -1; } } if (s != _start) { - samplepos_t const old = _start; + Temporal::timepos_t const old = _start; _start = s; - if (allow_beat_recompute) { - recompute_beat_from_samples (sub_num); - } start_changed (this); /* EMIT SIGNAL */ StartChanged (); /* EMIT SIGNAL */ if (is_session_range ()) { - Session::StartTimeChanged (old); /* EMIT SIGNAL */ - AudioFileSource::set_header_position_offset (s); + Session::StartTimeChanged (old.samples()); /* emit signal */ + AudioFileSource::set_header_position_offset (s.samples()); } } - assert (_start >= 0); + assert (_start.positive() || _start.zero()); return 0; } -/** Set end position. - * @param s New end. +/** set end position. + * @param s new end. * @param force true to force setting, even if the given new end is before the current start. - * @param allow_beat_recompute True to recompute BEAT end time from the new given end time. */ int -Location::set_end (samplepos_t e, bool force, bool allow_beat_recompute, const uint32_t sub_num) +Location::set_end (Temporal::timepos_t const & e, bool force) { - if (e < 0) { - return -1; - } - if (_locked) { return -1; } @@ -294,13 +256,10 @@ Location::set_end (samplepos_t e, bool force, bool allow_beat_recompute, const u if (_start != e) { _start = e; _end = e; - if (allow_beat_recompute) { - recompute_beat_from_samples (sub_num); - } - //start_changed (this); /* EMIT SIGNAL */ - //StartChanged (); /* EMIT SIGNAL */ - end_changed (this); /* EMIT SIGNAL */ - EndChanged (); /* EMIT SIGNAL */ + //start_changed (this); /* emit signal */ + //startchanged (); /* emit signal */ + end_changed (this); /* emit signal */ + EndChanged (); /* emit signal */ } assert (_start >= 0); @@ -309,40 +268,32 @@ Location::set_end (samplepos_t e, bool force, bool allow_beat_recompute, const u return 0; } else if (!force) { /* range locations must exceed a minimum duration */ - if (e - _start < Config->get_range_location_minimum()) { + if (_start.distance (e) < Config->get_range_location_minimum()) { return -1; } } if (e != _end) { - samplepos_t const old = _end; + timepos_t const old = _end; _end = e; - if (allow_beat_recompute) { - recompute_beat_from_samples (sub_num); - } - end_changed(this); /* EMIT SIGNAL */ EndChanged(); /* EMIT SIGNAL */ if (is_session_range()) { - Session::EndTimeChanged (old); /* EMIT SIGNAL */ + Session::EndTimeChanged (old.samples()); /* EMIT SIGNAL */ } } - assert (_end >= 0); + assert (_end.positive() || _end.zero()); return 0; } int -Location::set (samplepos_t s, samplepos_t e, bool allow_beat_recompute, const uint32_t sub_num) +Location::set (Temporal::timepos_t const & s, Temporal::timepos_t const & e) { - if (s < 0 || e < 0) { - return -1; - } - /* check validity */ if (((is_auto_punch() || is_auto_loop()) && s >= e) || (!is_mark() && s > e)) { return -1; @@ -356,11 +307,6 @@ Location::set (samplepos_t s, samplepos_t e, bool allow_beat_recompute, const ui if (_start != s) { _start = s; _end = s; - - if (allow_beat_recompute) { - recompute_beat_from_samples (sub_num); - } - start_change = true; end_change = true; } @@ -371,45 +317,35 @@ Location::set (samplepos_t s, samplepos_t e, bool allow_beat_recompute, const ui } else { /* range locations must exceed a minimum duration */ - if (e - s < Config->get_range_location_minimum()) { + if (s.distance (e) < Config->get_range_location_minimum()) { return -1; } if (s != _start) { - samplepos_t const old = _start; + Temporal::timepos_t const old = _start; _start = s; - - if (allow_beat_recompute) { - recompute_beat_from_samples (sub_num); - } - start_change = true; if (is_session_range ()) { - Session::StartTimeChanged (old); /* EMIT SIGNAL */ - AudioFileSource::set_header_position_offset (s); + Session::StartTimeChanged (old.samples()); /* EMIT SIGNAL */ + AudioFileSource::set_header_position_offset (s.samples()); } } if (e != _end) { - samplepos_t const old = _end; + Temporal::timepos_t const old = _end; _end = e; - - if (allow_beat_recompute) { - recompute_beat_from_samples (sub_num); - } - end_change = true; if (is_session_range()) { - Session::EndTimeChanged (old); /* EMIT SIGNAL */ + Session::EndTimeChanged (old.samples()); /* EMIT SIGNAL */ } } - assert (_end >= 0); + assert (e.positive() || e.zero()); } if (start_change && end_change) { @@ -427,20 +363,16 @@ Location::set (samplepos_t s, samplepos_t e, bool allow_beat_recompute, const ui } int -Location::move_to (samplepos_t pos, const uint32_t sub_num) +Location::move_to (Temporal::timepos_t const & pos) { - if (pos < 0) { - return -1; - } - if (_locked) { return -1; } if (_start != pos) { + const timecnt_t len = _start.distance (_end); _start = pos; - _end = _start + length(); - recompute_beat_from_samples (sub_num); + _end = pos + len; changed (this); /* EMIT SIGNAL */ Changed (); /* EMIT SIGNAL */ @@ -496,7 +428,7 @@ Location::set_is_clock_origin (bool yn, void*) void Location::set_skip (bool yn) { - if (is_range_marker() && length() > 0) { + if (is_range_marker() && length_samples() > 0) { if (set_flag_internal (yn, IsSkip)) { flags_changed (this); FlagsChanged (); @@ -507,7 +439,7 @@ Location::set_skip (bool yn) void Location::set_skipping (bool yn) { - if (is_range_marker() && is_skip() && length() > 0) { + if (is_range_marker() && is_skip() && length_samples() > 0) { if (set_flag_internal (yn, IsSkipping)) { flags_changed (this); FlagsChanged (); @@ -598,13 +530,8 @@ Location::get_state () node->set_property ("name", name()); node->set_property ("start", start()); node->set_property ("end", end()); - if (position_lock_style() == MusicTime) { - node->set_property ("start-beat", _start_beat); - node->set_property ("end-beat", _end_beat); - } node->set_property ("flags", _flags); node->set_property ("locked", _locked); - node->set_property ("position-lock-style", _position_lock_style); node->set_property ("timestamp", _timestamp); if (_scene_change) { node->add_child_nocopy (_scene_change->get_state()); @@ -690,67 +617,38 @@ Location::set_state (const XMLNode& node, int version) cd_info[cd_name] = cd_value; } - node.get_property ("position-lock-style", _position_lock_style); - XMLNode* scene_child = find_named_node (node, SceneChange::xml_node_name); if (scene_child) { _scene_change = SceneChange::factory (*scene_child, version); } - if (position_lock_style() == AudioTime) { - recompute_beat_from_samples (0); - } else{ - /* music */ - if (!node.get_property ("start-beat", _start_beat) || - !node.get_property ("end-beat", _end_beat)) { - recompute_beat_from_samples (0); - } - } - - changed (this); /* EMIT SIGNAL */ Changed (); /* EMIT SIGNAL */ - assert (_start >= 0); - assert (_end >= 0); + assert (_start.positive() || _start.zero()); + assert (_end.positive() || _end.zero()); return 0; } void -Location::set_position_lock_style (PositionLockStyle ps) +Location::set_position_time_domain (TimeDomain domain) { - if (_position_lock_style == ps) { + if (_start.time_domain() == domain) { return; } - _position_lock_style = ps; - - if (ps == MusicTime) { - recompute_beat_from_samples (0); + if (domain == Temporal::BeatTime) { + _start = timepos_t (_start.beats()); + _end = timepos_t (_end.beats()); + } else { + _start = timepos_t (_start.samples()); + _end = timepos_t (_end.samples()); } - position_lock_style_changed (this); /* EMIT SIGNAL */ - PositionLockStyleChanged (); /* EMIT SIGNAL */ -} - -void -Location::recompute_beat_from_samples (const uint32_t sub_num) -{ - _start_beat = _session.tempo_map().exact_beat_at_sample (_start, sub_num); - _end_beat = _session.tempo_map().exact_beat_at_sample (_end, sub_num); -} - -void -Location::recompute_samples_from_beat () -{ - if (_position_lock_style != MusicTime) { - return; - } - - TempoMap& map (_session.tempo_map()); - set (map.sample_at_beat (_start_beat), map.sample_at_beat (_end_beat), false); + position_time_domain_changed (this); /* EMIT SIGNAL */ + TimeDomainChanged (); /* EMIT SIGNAL */ } void @@ -1184,11 +1082,10 @@ Locations::set_state (const XMLNode& node, int version) Location* session_range_location = 0; if (version < 3000) { - session_range_location = new Location (_session, 0, 0, _("session"), Location::IsSessionRange, 0); + session_range_location = new Location (_session, timepos_t (Temporal::AudioTime), timepos_t (Temporal::AudioTime), _("session"), Location::IsSessionRange); new_locations.push_back (session_range_location); } - XMLNodeConstIterator niter; for (niter = nlist.begin(); niter != nlist.end(); ++niter) { @@ -1358,10 +1255,10 @@ Locations::mark_at (samplepos_t pos, samplecnt_t slop) const for (LocationList::const_iterator i = locations.begin(); i != locations.end(); ++i) { if ((*i)->is_mark()) { - if (pos > (*i)->start()) { - delta = pos - (*i)->start(); + if (pos > (*i)->start_sample()) { + delta = pos - (*i)->start_sample(); } else { - delta = (*i)->start() - pos; + delta = (*i)->start_sample() - pos; } if (slop == 0 && delta == 0) { @@ -1388,10 +1285,11 @@ Locations::first_mark_after (samplepos_t sample, bool include_special_ranges) { Glib::Threads::RWLock::ReaderLock lm (_lock); + for (LocationList::iterator i = locations.begin(); i != locations.end(); ++i) { - locs.push_back (make_pair ((*i)->start(), (*i))); + locs.push_back (make_pair ((*i)->start_sample(), (*i))); if (!(*i)->is_mark()) { - locs.push_back (make_pair ((*i)->end(), (*i))); + locs.push_back (make_pair ((*i)->end_sample(), (*i))); } } } @@ -1419,14 +1317,14 @@ Locations::first_mark_after (samplepos_t sample, bool include_special_ranges) /** Look for the `marks' (either locations which are marks, or start/end points of range markers) either * side of a sample. Note that if sample is exactly on a `mark', that mark will not be considered for returning * as before/after. - * @param sample Frame to look for. - * @param before Filled in with the position of the last `mark' before `sample' (or max_samplepos if none exists) - * @param after Filled in with the position of the next `mark' after `sample' (or max_samplepos if none exists) + * @param pos position to be used + * @param before Filled in with the position of the last `mark' before `pos' (or max_timepos if none exists) + * @param after Filled in with the position of the next `mark' after `pos' (or max_timepos if none exists) */ void -Locations::marks_either_side (samplepos_t const sample, samplepos_t& before, samplepos_t& after) const +Locations::marks_either_side (timepos_t const & pos, timepos_t& before, timepos_t& after) const { - before = after = max_samplepos; + before = after = std::numeric_limits::max(); LocationList locs; @@ -1437,7 +1335,7 @@ Locations::marks_either_side (samplepos_t const sample, samplepos_t& before, sam /* Get a list of positions; don't store any that are exactly on our requested position */ - std::list positions; + std::list positions; for (LocationList::const_iterator i = locs.begin(); i != locs.end(); ++i) { if (((*i)->is_auto_loop() || (*i)->is_auto_punch()) || (*i)->is_xrun()) { @@ -1446,14 +1344,14 @@ Locations::marks_either_side (samplepos_t const sample, samplepos_t& before, sam if (!(*i)->is_hidden()) { if ((*i)->is_mark ()) { - if ((*i)->start() != sample) { + if ((*i)->start() != pos) { positions.push_back ((*i)->start ()); } } else { - if ((*i)->start() != sample) { + if ((*i)->start() != pos) { positions.push_back ((*i)->start ()); } - if ((*i)->end() != sample) { + if ((*i)->end() != pos) { positions.push_back ((*i)->end ()); } } @@ -1466,8 +1364,9 @@ Locations::marks_either_side (samplepos_t const sample, samplepos_t& before, sam positions.sort (); - std::list::iterator i = positions.begin (); - while (i != positions.end () && *i < sample) { + std::list::iterator i = positions.begin (); + + while (i != positions.end () && *i < pos) { ++i; } @@ -1567,7 +1466,7 @@ Locations::get_location_by_id(PBD::ID id) } void -Locations::find_all_between (samplepos_t start, samplepos_t end, LocationList& ll, Location::Flags flags) +Locations::find_all_between (timepos_t const & start, timepos_t const & end, LocationList& ll, Location::Flags flags) { Glib::Threads::RWLock::ReaderLock lm (_lock); for (LocationList::const_iterator i = locations.begin(); i != locations.end(); ++i) { diff --git a/libs/ardour/lua_api.cc b/libs/ardour/lua_api.cc index 929c99231c..0cf23a0aea 100644 --- a/libs/ardour/lua_api.cc +++ b/libs/ardour/lua_api.cc @@ -913,7 +913,7 @@ LuaAPI::Vamp::initialize () } int -LuaAPI::Vamp::analyze (boost::shared_ptr r, uint32_t channel, luabridge::LuaRef cb) +LuaAPI::Vamp::analyze (boost::shared_ptr r, uint32_t channel, luabridge::LuaRef cb) { if (!_initialized) { if (!initialize ()) { @@ -926,7 +926,7 @@ LuaAPI::Vamp::analyze (boost::shared_ptr r, uint32_t channel, float* data = new float[_bufsize]; float* bufs[1] = { data }; - samplecnt_t len = r->readable_length(); + samplecnt_t len = r->readable_length_samples(); samplepos_t pos = 0; int rv = 0; @@ -1003,9 +1003,9 @@ LuaAPI::Rubberband::Rubberband (boost::shared_ptr r, bool percussiv , _cb (0) { _n_channels = r->n_channels (); - _read_len = r->length () / (double)r->stretch (); - _read_start = r->ancestral_start () + samplecnt_t (r->start () / (double)r->stretch ()); - _read_offset = _read_start - r->start () + r->position (); + _read_len = r->length_samples () / (double)r->stretch (); + _read_start = r->ancestral_start_sample () + samplecnt_t (r->start_sample () / (double)r->stretch ()); + _read_offset = _read_start - r->start_sample () + r->position_sample (); } LuaAPI::Rubberband::~Rubberband () @@ -1052,13 +1052,13 @@ LuaAPI::Rubberband::read (Sample* buf, samplepos_t pos, samplecnt_t cnt, int cha static void null_deleter (LuaAPI::Rubberband*) {} -boost::shared_ptr +boost::shared_ptr LuaAPI::Rubberband::readable () { if (!_self) { _self = boost::shared_ptr (this, &null_deleter); } - return boost::dynamic_pointer_cast (_self); + return boost::dynamic_pointer_cast (_self); } bool @@ -1205,7 +1205,7 @@ LuaAPI::Rubberband::finalize () boost::shared_ptr afs = boost::dynamic_pointer_cast (*i); assert (afs); afs->done_with_peakfile_writes (); - afs->update_header (_region->position (), *now, xnow); + afs->update_header (_region->position_sample (), *now, xnow); afs->mark_immutable (); Analyser::queue_source_for_analysis (*i, false); sl.push_back (*i); @@ -1216,10 +1216,10 @@ LuaAPI::Rubberband::finalize () PropertyList plist; plist.add (Properties::start, 0); - plist.add (Properties::length, _region->length ()); + plist.add (Properties::length, _region->length_samples ()); plist.add (Properties::name, region_name); plist.add (Properties::whole_file, true); - plist.add (Properties::position, _region->position ()); + plist.add (Properties::position, _region->position_sample ()); boost::shared_ptr r = RegionFactory::create (sl, plist); boost::shared_ptr ar = boost::dynamic_pointer_cast (r); @@ -1231,9 +1231,9 @@ LuaAPI::Rubberband::finalize () ar->set_fade_out (_region->fade_out ()); *(ar->envelope ()) = *(_region->envelope ()); - ar->set_ancestral_data (_read_start, _read_len, _stretch_ratio, _pitch_ratio); + ar->set_ancestral_data (timecnt_t (_read_start), timecnt_t (_read_len), _stretch_ratio, _pitch_ratio); ar->set_master_sources (_region->master_sources ()); - ar->set_length (ar->length () * _stretch_ratio, 0); // XXX + ar->set_length (ar->nt_length () * _stretch_ratio); // XXX if (_stretch_ratio != 1.0) { // TODO: apply mapping ar->envelope ()->x_scale (_stretch_ratio); diff --git a/libs/ardour/luabindings.cc b/libs/ardour/luabindings.cc index 35f757936d..9dacc1e0b5 100644 --- a/libs/ardour/luabindings.cc +++ b/libs/ardour/luabindings.cc @@ -26,10 +26,10 @@ #include "pbd/openuri.h" #include "temporal/bbt_time.h" +#include "temporal/range.h" #include "evoral/Control.h" #include "evoral/ControlList.h" -#include "evoral/Range.h" #include "ardour/amp.h" #include "ardour/async_midi_port.h" @@ -199,7 +199,6 @@ CLASSKEYS(Selectable*); CLASSKEYS(std::list); CLASSKEYS(ARDOUR::AudioEngine); -CLASSKEYS(ARDOUR::BeatsSamplesConverter); CLASSKEYS(ARDOUR::BufferSet); CLASSKEYS(ARDOUR::ChanCount); CLASSKEYS(ARDOUR::ChanMapping); @@ -254,7 +253,7 @@ CLASSKEYS(std::list); CLASSKEYS(std::vector); CLASSKEYS(std::vector >); CLASSKEYS(std::vector >); -CLASSKEYS(std::vector >); +CLASSKEYS(std::vector >); CLASSKEYS(std::vector); CLASSKEYS(std::list >); // PluginInfoList @@ -281,7 +280,7 @@ CLASSKEYS(boost::shared_ptr); CLASSKEYS(boost::shared_ptr); CLASSKEYS(boost::shared_ptr); CLASSKEYS(boost::shared_ptr); -CLASSKEYS(boost::shared_ptr); +CLASSKEYS(boost::shared_ptr); CLASSKEYS(boost::shared_ptr); CLASSKEYS(boost::shared_ptr); CLASSKEYS(boost::shared_ptr); @@ -582,7 +581,7 @@ LuaBindings::common (lua_State* L) .addFunction ("set_interpolation", &Evoral::ControlList::set_interpolation) .addFunction ("truncate_end", &Evoral::ControlList::truncate_end) .addFunction ("truncate_start", &Evoral::ControlList::truncate_start) - .addFunction ("clear", (void (Evoral::ControlList::*)(double, double))&Evoral::ControlList::clear) + .addFunction ("clear", (void (Evoral::ControlList::*)(timepos_t const &, timepos_t const &))&Evoral::ControlList::clear) .addFunction ("clear_list", (void (Evoral::ControlList::*)())&Evoral::ControlList::clear) .addFunction ("in_write_pass", &Evoral::ControlList::in_write_pass) .addFunction ("events", &Evoral::ControlList::events) @@ -605,10 +604,11 @@ LuaBindings::common (lua_State* L) .addData ("logarithmic", &Evoral::ParameterDescriptor::logarithmic) .endClass () - .beginClass > ("Range") - .addConstructor () - .addData ("from", &Evoral::Range::from) - .addData ("to", &Evoral::Range::to) + .beginClass ("Range") + .addConstructor () + .addFunction ("start", &Temporal::Range::start) + /* "end is a reserved Lua word */ + .addFunction ("_end", &Temporal::Range::end) .endClass () .deriveWSPtrClass , Evoral::ControlSet> ("Sequence") @@ -771,20 +771,13 @@ LuaBindings::common (lua_State* L) .beginClass ("Progress") .endClass () - .beginClass ("MusicSample") - .addConstructor () - .addFunction ("set", &MusicSample::set) - .addData ("sample", &MusicSample::sample) - .addData ("division", &MusicSample::division) - .endClass () - - .beginClass ("AudioRange") - .addConstructor () - .addFunction ("length", &AudioRange::length) - .addFunction ("equal", &AudioRange::equal) - .addData ("start", &AudioRange::start) - .addData ("_end", &AudioRange::end) // XXX "end" is a lua reserved word - .addData ("id", &AudioRange::id) + .beginClass ("TimelineRange") + .addConstructor () + .addFunction ("length", &TimelineRange::length) + .addFunction ("equal", &TimelineRange::equal) + .addFunction ("start", &TimelineRange::start) + .addFunction ("_end", &TimelineRange::end) // XXX "end" is a lua reserved word + .addData ("id", &TimelineRange::id) .endClass () .beginWSPtrClass ("PluginInfo") @@ -1166,7 +1159,7 @@ LuaBindings::common (lua_State* L) .addFunction ("lower_region", &Playlist::lower_region) .addFunction ("raise_region_to_top", &Playlist::raise_region_to_top) .addFunction ("lower_region_to_bottom", &Playlist::lower_region_to_bottom) - .addFunction ("duplicate", (void (Playlist::*)(boost::shared_ptr, samplepos_t, samplecnt_t, float))&Playlist::duplicate) + .addFunction ("duplicate", (void (Playlist::*)(boost::shared_ptr, timepos_t &, timecnt_t const &, float))&Playlist::duplicate) .addFunction ("duplicate_until", &Playlist::duplicate_until) .addFunction ("duplicate_range", &Playlist::duplicate_range) .addFunction ("combine", &Playlist::combine) @@ -1178,7 +1171,7 @@ LuaBindings::common (lua_State* L) .addFunction ("split_region", &Playlist::split_region) .addFunction ("get_orig_track_id", &Playlist::get_orig_track_id) //.addFunction ("split", &Playlist::split) // XXX needs MusicSample - .addFunction ("cut", (boost::shared_ptr (Playlist::*)(std::list&, bool))&Playlist::cut) + .addFunction ("cut", (boost::shared_ptr (Playlist::*)(std::list&, bool))&Playlist::cut) #if 0 .addFunction ("copy", &Playlist::copy) .addFunction ("paste", &Playlist::paste) @@ -1239,28 +1232,27 @@ LuaBindings::common (lua_State* L) .addFunction ("write_immediate_event", &MidiTrack::write_immediate_event) .endClass () - .beginWSPtrClass ("Readable") - .addFunction ("read", &Readable::read) - .addFunction ("readable_length", &Readable::readable_length) - .addFunction ("n_channels", &Readable::n_channels) - .addStaticFunction ("load", &Readable::load) + .beginWSPtrClass ("Readable") + .addFunction ("read", &AudioReadable::read) + .addFunction ("readable_length", &AudioReadable::readable_length_samples) + .addFunction ("n_channels", &AudioReadable::n_channels) + .addStaticFunction ("load", &AudioReadable::load) .endClass () - .deriveWSPtrClass ("AudioRom") + .deriveWSPtrClass ("AudioRom") .addStaticFunction ("new_rom", &AudioRom::new_rom) .endClass () .deriveWSPtrClass ("Region") - .addCast ("to_readable") .addCast ("to_midiregion") .addCast ("to_audioregion") .addFunction ("playlist", &Region::playlist) .addFunction ("set_name", &Region::set_name) /* properties */ - .addFunction ("position", &Region::position) - .addFunction ("start", &Region::start) - .addFunction ("length", &Region::length) + .addFunction ("position", &Region::nt_position) + .addFunction ("start", &Region::nt_start) + .addFunction ("length", &Region::nt_length) .addFunction ("layer", &Region::layer) .addFunction ("data_type", &Region::data_type) .addFunction ("stretch", &Region::stretch) @@ -1280,7 +1272,7 @@ LuaBindings::common (lua_State* L) .addFunction ("sync_marked", &Region::sync_marked) .addFunction ("external", &Region::external) .addFunction ("import", &Region::import) - .addFunction ("covers", &Region::covers) + .addFunction ("covers", (bool (Region::*)(timepos_t const &) const) &Region::covers) .addFunction ("at_natural_position", &Region::at_natural_position) .addFunction ("is_compound", &Region::is_compound) .addFunction ("captured_xruns", &Region::captured_xruns) @@ -1298,7 +1290,6 @@ LuaBindings::common (lua_State* L) .addFunction ("move_start", &Region::move_start) .addFunction ("master_sources", &Region::master_sources) .addFunction ("master_source_names", &Region::master_source_names) - .addFunction ("n_channels", &Region::n_channels) .addFunction ("trim_front", &Region::trim_front) .addFunction ("trim_end", &Region::trim_end) .addFunction ("trim_to", &Region::trim_to) @@ -1310,7 +1301,6 @@ LuaBindings::common (lua_State* L) .addFunction ("lower_to_bottom", &Region::lower_to_bottom) .addFunction ("set_sync_position", &Region::set_sync_position) .addFunction ("clear_sync_position", &Region::clear_sync_position) - .addFunction ("quarter_note", &Region::quarter_note) .addFunction ("set_hidden", &Region::set_hidden) .addFunction ("set_muted", &Region::set_muted) .addFunction ("set_opaque", &Region::set_opaque) @@ -1325,11 +1315,11 @@ LuaBindings::common (lua_State* L) .addFunction ("do_export", &MidiRegion::do_export) .addFunction ("midi_source", &MidiRegion::midi_source) .addFunction ("model", (boost::shared_ptr (MidiRegion::*)())&MidiRegion::model) - .addFunction ("start_beats", &MidiRegion::start_beats) - .addFunction ("length_beats", &MidiRegion::length_beats) .endClass () .deriveWSPtrClass ("AudioRegion") + .addCast ("to_readable") + .addFunction ("n_channels", &AudioRegion::n_channels) .addFunction ("audio_source", &AudioRegion::audio_source) .addFunction ("set_scale_amplitude", &AudioRegion::set_scale_amplitude) .addFunction ("scale_amplitude", &AudioRegion::scale_amplitude) @@ -1383,8 +1373,8 @@ LuaBindings::common (lua_State* L) .endClass () .deriveWSPtrClass ("AudioSource") - .addCast ("to_readable") - .addFunction ("readable_length", &AudioSource::readable_length) + .addCast ("to_readable") + .addFunction ("readable_length", &AudioSource::readable_length_samples) .addFunction ("n_channels", &AudioSource::n_channels) .addFunction ("empty", &Source::empty) .addFunction ("length", &Source::length) @@ -1745,7 +1735,7 @@ LuaBindings::common (lua_State* L) .endClass () .deriveWSPtrClass ("AudioSource") - .addFunction ("readable_length", &AudioSource::readable_length) + .addFunction ("readable_length", &AudioSource::readable_length_samples) .addFunction ("n_channels", &AudioSource::n_channels) .endClass () @@ -1795,8 +1785,8 @@ LuaBindings::common (lua_State* L) .beginStdVector > ("SourceList") .endClass () - // typedef std::vector > - .beginStdVector > ("ReadableList") + // typedef std::vector > + .beginStdVector > ("ReadableList") .endClass () // from SessionPlaylists: std::vector > @@ -1844,17 +1834,12 @@ LuaBindings::common (lua_State* L) .beginConstStdList > ("PortList") .endClass () - // used by Playlist::cut/copy - .beginConstStdList ("AudioRangeList") - .endClass () - .beginConstStdCPtrList ("LocationList") .endClass () .beginConstStdVector ("ParameterList") .endClass () - // std::list > ControlList .beginStdList > ("ControlList") .endClass () @@ -1897,12 +1882,6 @@ LuaBindings::common (lua_State* L) .addFunction ("samples_per_grid", &Meter::samples_per_grid) .endClass () - .beginClass ("BeatsSamplesConverter") - .addConstructor () - .addFunction ("to", &BeatsSamplesConverter::to) - .addFunction ("from", &BeatsSamplesConverter::from) - .endClass () - .beginClass ("TempoMap") .addFunction ("add_tempo", &TempoMap::add_tempo) .addFunction ("add_meter", &TempoMap::add_meter) @@ -2666,7 +2645,7 @@ LuaBindings::common (lua_State* L) .addFunction ("set_strech_and_pitch", &ARDOUR::LuaAPI::Rubberband::set_strech_and_pitch) .addFunction ("set_mapping", &ARDOUR::LuaAPI::Rubberband::set_mapping) .addFunction ("process", &ARDOUR::LuaAPI::Rubberband::process) - .addFunction ("readable_length", &ARDOUR::LuaAPI::Rubberband::readable_length) + .addFunction ("readable_length", &ARDOUR::LuaAPI::Rubberband::readable_length_samples) .addFunction ("n_channels", &ARDOUR::LuaAPI::Rubberband::n_channels) .addFunction ("readable", &ARDOUR::LuaAPI::Rubberband::readable) .endClass () diff --git a/libs/ardour/lv2_plugin.cc b/libs/ardour/lv2_plugin.cc index 4e8ab9d475..0e76991779 100644 --- a/libs/ardour/lv2_plugin.cc +++ b/libs/ardour/lv2_plugin.cc @@ -2934,9 +2934,9 @@ LV2Plugin::connect_and_run(BufferSet& bufs, assert (start + samples - _current_latency >= 0); if (c->guard) { c->guard = false; - c->ac->list()->add (when, v, true, true); + c->ac->list()->add (timepos_t (when), v, true, true); } else { - c->ac->set_double (v, when, true); + c->ac->set_double (v, timepos_t (when), true); } } } @@ -2993,7 +2993,7 @@ LV2Plugin::connect_and_run(BufferSet& bufs, AutomationCtrlPtr c = get_automation_control (p); DEBUG_TRACE(DEBUG::LV2Automate, string_compose ("Start Touch p: %1\n", p)); if (c) { - c->ac->start_touch (std::max ((samplepos_t)0, start - _current_latency)); + c->ac->start_touch (timepos_t (std::max ((samplepos_t)0, start - _current_latency))); c->guard = true; } } @@ -3008,7 +3008,7 @@ LV2Plugin::connect_and_run(BufferSet& bufs, AutomationCtrlPtr c = get_automation_control (p); DEBUG_TRACE(DEBUG::LV2Automate, string_compose ("End Touch p: %1\n", p)); if (c) { - c->ac->stop_touch (std::max ((samplepos_t)0, start - _current_latency)); + c->ac->stop_touch (timepos_t (std::max ((samplepos_t)0, start - _current_latency))); } } } diff --git a/libs/ardour/midi_model.cc b/libs/ardour/midi_model.cc index d26eabc2f3..3ad6ced01e 100644 --- a/libs/ardour/midi_model.cc +++ b/libs/ardour/midi_model.cc @@ -1472,16 +1472,16 @@ MidiModel::resolve_overlaps_unlocked (const NotePtr note, void* arg) TimeType sb = (*i)->time(); TimeType eb = (*i)->end_time(); - OverlapType overlap = OverlapNone; + Temporal::OverlapType overlap = Temporal::OverlapNone; if ((sb > sa) && (eb <= ea)) { - overlap = OverlapInternal; + overlap = Temporal::OverlapInternal; } else if ((eb > sa) && (eb <= ea)) { - overlap = OverlapStart; + overlap = Temporal::OverlapStart; } else if ((sb > sa) && (sb < ea)) { - overlap = OverlapEnd; + overlap = Temporal::OverlapEnd; } else if ((sa >= sb) && (sa <= eb) && (ea <= eb)) { - overlap = OverlapExternal; + overlap = Temporal::OverlapExternal; } else { /* no overlap */ continue; @@ -1497,7 +1497,7 @@ MidiModel::resolve_overlaps_unlocked (const NotePtr note, void* arg) } switch (overlap) { - case OverlapStart: + case Temporal::OverlapStart: cerr << "OverlapStart\n"; /* existing note covers start of new note */ switch (insert_merge_policy()) { @@ -1530,7 +1530,7 @@ MidiModel::resolve_overlaps_unlocked (const NotePtr note, void* arg) } break; - case OverlapEnd: + case Temporal::OverlapEnd: cerr << "OverlapEnd\n"; /* existing note covers end of new note */ switch (insert_merge_policy()) { @@ -1566,7 +1566,7 @@ MidiModel::resolve_overlaps_unlocked (const NotePtr note, void* arg) } break; - case OverlapExternal: + case Temporal::OverlapExternal: cerr << "OverlapExt\n"; /* existing note overlaps all the new note */ switch (insert_merge_policy()) { @@ -1585,7 +1585,7 @@ MidiModel::resolve_overlaps_unlocked (const NotePtr note, void* arg) } break; - case OverlapInternal: + case Temporal::OverlapInternal: cerr << "OverlapInt\n"; /* new note fully overlaps an existing note */ switch (insert_merge_policy()) { @@ -1784,7 +1784,7 @@ MidiModel::insert_silence_at_start (TimeType t) for (Controls::iterator i = controls().begin(); i != controls().end(); ++i) { boost::shared_ptr ac = boost::dynamic_pointer_cast (i->second); XMLNode& before = ac->alist()->get_state (); - i->second->list()->shift (0, t.to_double()); + i->second->list()->shift (timepos_t::zero (i->second->list()->time_domain()), timecnt_t (t)); XMLNode& after = ac->alist()->get_state (); s->session().add_command (new MementoCommand (new MidiAutomationListBinder (s, i->first), &before, &after)); } @@ -1801,7 +1801,7 @@ MidiModel::insert_silence_at_start (TimeType t) apply_command_as_subcommand (s->session(), c); } - ContentsShifted (t.to_double()); + ContentsShifted (timecnt_t (t)); } void diff --git a/libs/ardour/midi_playlist.cc b/libs/ardour/midi_playlist.cc index 42a43f1804..3d3602e5df 100644 --- a/libs/ardour/midi_playlist.cc +++ b/libs/ardour/midi_playlist.cc @@ -78,8 +78,8 @@ MidiPlaylist::MidiPlaylist (boost::shared_ptr other, string } MidiPlaylist::MidiPlaylist (boost::shared_ptr other, - samplepos_t start, - samplecnt_t dur, + timepos_t const & start, + timepos_t const & dur, string name, bool hidden) : Playlist (other, start, dur, name, hidden) @@ -149,9 +149,9 @@ MidiPlaylist::dump () const for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) { r = *i; cerr << " " << r->name() << " @ " << r << " [" - << r->start() << "+" << r->length() + << r->nt_start() << "+" << r->nt_length() << "] at " - << r->position() + << r->nt_position() << " on layer " << r->layer () << endl; @@ -196,14 +196,14 @@ MidiPlaylist::destroy_region (boost::shared_ptr region) return changed; } void -MidiPlaylist::_split_region (boost::shared_ptr region, const MusicSample& playlist_position, ThawList& thawlist) +MidiPlaylist::_split_region (boost::shared_ptr region, timepos_t const & playlist_position, Thawlist& thawlist) { - if (!region->covers (playlist_position.sample)) { + if (!region->covers (playlist_position)) { return; } - if (region->position() == playlist_position.sample || - region->last_sample() == playlist_position.sample) { + if (region->nt_position() == playlist_position || + region->nt_last() == playlist_position) { return; } @@ -218,18 +218,16 @@ MidiPlaylist::_split_region (boost::shared_ptr region, const MusicSample string before_name; string after_name; - const double before_qn = _session.tempo_map().exact_qn_at_sample (playlist_position.sample, playlist_position.division) - region->quarter_note(); - const double after_qn = mr->length_beats() - before_qn; - MusicSample before (playlist_position.sample - region->position(), playlist_position.division); - MusicSample after (region->length() - before.sample, playlist_position.division); + + const timecnt_t before = region->nt_position().distance (playlist_position); + const timecnt_t after = region->nt_length() - before; RegionFactory::region_name (before_name, region->name(), false); { PropertyList plist; - plist.add (Properties::length, before.sample); - plist.add (Properties::length_beats, before_qn); + plist.add (Properties::length, before); plist.add (Properties::name, before_name); plist.add (Properties::left_of_split, true); plist.add (Properties::layering_index, region->layering_index ()); @@ -239,7 +237,7 @@ MidiPlaylist::_split_region (boost::shared_ptr region, const MusicSample since it supplies that offset to the Region constructor, which is necessary to get audio region gain envelopes right. */ - left = RegionFactory::create (region, MusicSample (0, 0), plist, true, &thawlist); + left = RegionFactory::create (region, plist, true, &thawlist); } RegionFactory::region_name (after_name, region->name(), false); @@ -247,8 +245,7 @@ MidiPlaylist::_split_region (boost::shared_ptr region, const MusicSample { PropertyList plist; - plist.add (Properties::length, after.sample); - plist.add (Properties::length_beats, after_qn); + plist.add (Properties::length, after); plist.add (Properties::name, after_name); plist.add (Properties::right_of_split, true); plist.add (Properties::layering_index, region->layering_index ()); @@ -258,8 +255,8 @@ MidiPlaylist::_split_region (boost::shared_ptr region, const MusicSample right = RegionFactory::create (region, before, plist, true, &thawlist); } - add_region_internal (left, region->position(), thawlist, 0, region->quarter_note(), true); - add_region_internal (right, region->position() + before.sample, thawlist, before.division, region->quarter_note() + before_qn, true); + add_region_internal (left, region->nt_position(), thawlist); + add_region_internal (right, region->nt_position() + before, thawlist); remove_region_internal (region, thawlist); } diff --git a/libs/ardour/midi_playlist_source.cc b/libs/ardour/midi_playlist_source.cc deleted file mode 100644 index d9242bcf34..0000000000 --- a/libs/ardour/midi_playlist_source.cc +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright (C) 2011-2015 David Robillard - * Copyright (C) 2011-2017 Paul Davis - * Copyright (C) 2014-2019 Robin Gareus - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifdef WAF_BUILD -#include "libardour-config.h" -#endif - -#include "pbd/error.h" - -#include "ardour/midi_playlist.h" -#include "ardour/midi_playlist_source.h" - -#include "pbd/i18n.h" - -using namespace std; -using namespace ARDOUR; -using namespace PBD; - -namespace ARDOUR { -class MidiStateTracker; -class Session; -template class MidiRingBuffer; -} - -namespace Evoral { -template class EventSink; -template class Event; -} - -/******************************************************************************* -As of May 2011, it appears too complex to support compound regions for MIDI -because of the need to be able to edit the data represented by the region. It -seems that it would be a better idea to render the consituent regions into a -new MIDI file and create a new region based on that, an operation we have been -calling "consolidate" - -This code has been in place as a stub in case anyone gets any brilliant ideas -on other ways to approach this issue. -********************************************************************************/ - -MidiPlaylistSource::MidiPlaylistSource (Session& s, const ID& orig, const std::string& name, boost::shared_ptr p, - uint32_t /*chn*/, sampleoffset_t begin, samplecnt_t len, Source::Flag flags) - : Source (s, DataType::MIDI, name) - , MidiSource (s, name, flags) - , PlaylistSource (s, orig, name, p, DataType::MIDI, begin, len, flags) -{ -} - -MidiPlaylistSource::MidiPlaylistSource (Session& s, const XMLNode& node) - : Source (s, node) - , MidiSource (s, node) - , PlaylistSource (s, node) -{ - /* PlaylistSources are never writable, renameable or removable */ - _flags = Flag (_flags & ~(Writable|CanRename|Removable|RemovableIfEmpty|RemoveAtDestroy)); - - /* ancestors have already called ::set_state() in their XML-based - constructors. - */ - - if (set_state (node, Stateful::loading_state_version, false)) { - throw failed_constructor (); - } -} - -MidiPlaylistSource::~MidiPlaylistSource () -{ -} - -XMLNode& -MidiPlaylistSource::get_state () -{ - XMLNode& node (MidiSource::get_state ()); - - /* merge PlaylistSource state */ - - PlaylistSource::add_state (node); - - return node; -} - -int -MidiPlaylistSource::set_state (const XMLNode& node, int version) -{ - return set_state (node, version, true); -} - -int -MidiPlaylistSource::set_state (const XMLNode& node, int version, bool with_descendants) -{ - if (with_descendants) { - if (Source::set_state (node, version) || - MidiSource::set_state (node, version) || - PlaylistSource::set_state (node, version)) { - return -1; - } - } - - return 0; -} - -samplecnt_t -MidiPlaylistSource::length (samplepos_t) const -{ - pair extent = _playlist->get_extent(); - return extent.second - extent.first; -} - -samplecnt_t -MidiPlaylistSource::read_unlocked (const Lock& lock, - Evoral::EventSink& dst, - samplepos_t /*position*/, - samplepos_t start, - samplecnt_t cnt, - Evoral::Range* loop_range, - MidiStateTracker*, - MidiChannelFilter*) const -{ - boost::shared_ptr mp = boost::dynamic_pointer_cast (_playlist); - - if (!mp) { - return 0; - } - - /* XXX paul says on Oct 26 2019: - - rgareus: so to clarify now that i have better perspective: the API i want to get rid of is MidiPlaylist::read() ; everything that used it (i.e. the DiskReader) should use MidiPlaylist::rendered()->read() - rgareus: but a "read" operation is also a "write" operation: you have to put the data somewhere - rgareus: the only other user of MidiPlaylist::read() was MidiPlaylistSource (unsurprisingly), which as I noted is not even (really) used - rgareus: ::rendered() returns a ptr-to-RT_MidiBuffer, which has a read method which expects to write into a MidiBuffer, using push_back() - rgareus: but MidiPlaylistSource::read() is given an EventSink as the destination, and this does not (currently) have ::push_back(), only ::write() (which is willing to deal with inserts rather than appends) - rgareus: so, this is the API "mess" I'm trying to clean up. simple solution: since we don't use MidiPlaylistSource just comment out the line and forget about it for now, then remove MidiPlaylist::read() and move on - - This represents that decision, for now. - */ - - return cnt; // mp->read (dst, start, cnt, loop_range); -} - -samplecnt_t -MidiPlaylistSource::write_unlocked (const Lock&, - MidiRingBuffer&, - samplepos_t, - samplecnt_t) -{ - fatal << string_compose (_("programming error: %1"), "MidiPlaylistSource::write_unlocked() called - should be impossible") << endmsg; - abort(); /*NOTREACHED*/ - return 0; -} - -void -MidiPlaylistSource::append_event_beats(const Glib::Threads::Mutex::Lock& /*lock*/, const Evoral::Event& /*ev*/) -{ - fatal << string_compose (_("programming error: %1"), "MidiPlaylistSource::append_event_beats() called - should be impossible") << endmsg; - abort(); /*NOTREACHED*/ -} - -void -MidiPlaylistSource::append_event_samples(const Glib::Threads::Mutex::Lock& /*lock*/, const Evoral::Event& /* ev */, samplepos_t /*source_start*/) -{ - fatal << string_compose (_("programming error: %1"), "MidiPlaylistSource::append_event_samples() called - should be impossible") << endmsg; - abort(); /*NOTREACHED*/ -} - -void -MidiPlaylistSource::load_model (const Glib::Threads::Mutex::Lock&, bool) -{ - /* nothing to do */ -} - -void -MidiPlaylistSource::destroy_model (const Glib::Threads::Mutex::Lock&) -{ - /* nothing to do */ -} - -void -MidiPlaylistSource::flush_midi (const Lock& lock) -{ -} - - -bool -MidiPlaylistSource::empty () const -{ - return !_playlist || _playlist->empty(); -} diff --git a/libs/ardour/midi_region.cc b/libs/ardour/midi_region.cc index e94d34e8cc..899e3b95eb 100644 --- a/libs/ardour/midi_region.cc +++ b/libs/ardour/midi_region.cc @@ -60,18 +60,9 @@ using namespace std; using namespace ARDOUR; using namespace PBD; -namespace ARDOUR { - namespace Properties { - PBD::PropertyDescriptor start_beats; - PBD::PropertyDescriptor length_beats; - } -} - /* Basic MidiRegion constructor (many channels) */ MidiRegion::MidiRegion (const SourceList& srcs) : Region (srcs) - , _start_beats (Properties::start_beats, 0.0) - , _length_beats (Properties::length_beats, midi_source(0)->length_beats().to_double()) , _ignore_shift (false) { midi_source(0)->ModelChanged.connect_same_thread (_source_connection, boost::bind (&MidiRegion::model_changed, this)); @@ -82,8 +73,6 @@ MidiRegion::MidiRegion (const SourceList& srcs) MidiRegion::MidiRegion (boost::shared_ptr other) : Region (other) - , _start_beats (Properties::start_beats, other->_start_beats) - , _length_beats (Properties::length_beats, other->_length_beats) , _ignore_shift (false) { assert(_name.val().find("/") == string::npos); @@ -94,8 +83,6 @@ MidiRegion::MidiRegion (boost::shared_ptr other) /** Create a new MidiRegion that is part of an existing one */ MidiRegion::MidiRegion (boost::shared_ptr other, timecnt_t const & offset) : Region (other, offset) - , _start_beats (Properties::start_beats, other->_start_beats) - , _length_beats (Properties::length_beats, other->_length_beats) , _ignore_shift (false) { @@ -118,17 +105,13 @@ MidiRegion::do_export (string path) const /* caller must check for pre-existing file */ assert (!path.empty()); assert (!Glib::file_test (path, Glib::FILE_TEST_EXISTS)); - newsrc = boost::dynamic_pointer_cast(SourceFactory::createWritable(DataType::MIDI, _session, path, _session.sample_rate())); - - BeatsSamplesConverter bfc (_session.tempo_map(), _position); - Temporal::Beats const bbegin = bfc.from (_start); - Temporal::Beats const bend = bfc.from (_start + _length); + newsrc = boost::dynamic_pointer_cast(SourceFactory::createWritable(DataType::MIDI, _session, path, false, _session.sample_rate())); { /* Lock our source since we'll be reading from it. write_to() will take a lock on newsrc. */ Source::Lock lm (midi_source(0)->mutex()); - if (midi_source(0)->export_write_to (lm, newsrc, bbegin, bend)) { + if (midi_source(0)->export_write_to (lm, newsrc, _start.val().beats(), _start.val().beats() + _length.val().beats())) { return false; } } @@ -155,9 +138,8 @@ MidiRegion::clone (string path) const boost::shared_ptr MidiRegion::clone (boost::shared_ptr newsrc, ThawList* tl) const { - BeatsSamplesConverter bfc (_session.tempo_map(), _position); - Temporal::Beats const bbegin = bfc.from (_start); - Temporal::Beats const bend = bfc.from (_start + _length); + Temporal::Beats const bbegin = _start.val().beats (); + Temporal::Beats const bend = _start.val().beats() + _length.val().beats(); { boost::shared_ptr ms = midi_source(0); @@ -181,215 +163,80 @@ MidiRegion::clone (boost::shared_ptr newsrc, ThawList* tl) const plist.add (Properties::name, PBD::basename_nosuffix (newsrc->name())); plist.add (Properties::whole_file, true); plist.add (Properties::start, _start); - plist.add (Properties::start_beats, _start_beats); plist.add (Properties::length, _length); plist.add (Properties::position, _position); - plist.add (Properties::beat, _beat); - plist.add (Properties::length_beats, _length_beats); plist.add (Properties::layer, 0); boost::shared_ptr ret (boost::dynamic_pointer_cast (RegionFactory::create (newsrc, plist, true, tl))); - ret->set_quarter_note (quarter_note()); return ret; } -void -MidiRegion::post_set (const PropertyChange& pc) -{ - Region::post_set (pc); - - if (pc.contains (Properties::length) && !pc.contains (Properties::length_beats)) { - /* we're called by Stateful::set_values() which sends a change - only if the value is different from _current. - session load means we can clobber length_beats here in error (not all properties differ from current), - so disallow (this has been set from XML state anyway). - */ - if (!_session.loading()) { - update_length_beats (0); - } - } - - if (pc.contains (Properties::start) && !pc.contains (Properties::start_beats)) { - set_start_beats_from_start_samples (); - } -} - -void -MidiRegion::set_start_beats_from_start_samples () -{ - if (position_lock_style() == AudioTime) { - _start_beats = quarter_note() - _session.tempo_map().quarter_note_at_sample (_position - _start); - } -} - -void -MidiRegion::set_length_internal (samplecnt_t len, const int32_t sub_num) -{ - Region::set_length_internal (len, sub_num); - update_length_beats (sub_num); -} - -void -MidiRegion::update_after_tempo_map_change (bool /* send */) -{ - boost::shared_ptr pl (playlist()); - - if (!pl) { - return; - } - - const samplepos_t old_pos = _position; - const samplepos_t old_length = _length; - const samplepos_t old_start = _start; - - PropertyChange s_and_l; - - if (position_lock_style() == AudioTime) { - recompute_position_from_lock_style (0); - - /* - set _start to new position in tempo map. - - The user probably expects the region contents to maintain audio position as the - tempo changes, but AFAICT this requires modifying the src file to use - SMPTE timestamps with the current disk read model (?). - - We could arguably use _start to set _start_beats here, - resulting in viewport-like behaviour (the contents maintain - their musical position while the region is stationary). - - For now, the musical position at the region start is retained, but subsequent events - will maintain their beat distance according to the map. - */ - _start = _session.tempo_map().samples_between_quarter_notes (quarter_note() - start_beats(), quarter_note()); - - /* _length doesn't change for audio-locked regions. update length_beats to match. */ - _length_beats = _session.tempo_map().quarter_note_at_sample (_position + _length) - quarter_note(); - - s_and_l.add (Properties::start); - s_and_l.add (Properties::length_beats); - - send_change (s_and_l); - return; - } - - Region::update_after_tempo_map_change (false); - - /* _start has now been updated. */ - _length = max ((samplecnt_t) 1, _session.tempo_map().samples_between_quarter_notes (quarter_note(), quarter_note() + _length_beats)); - - if (old_start != _start) { - s_and_l.add (Properties::start); - } - if (old_length != _length) { - s_and_l.add (Properties::length); - } - if (old_pos != _position) { - s_and_l.add (Properties::position); - } - - send_change (s_and_l); -} - -void -MidiRegion::update_length_beats (const int32_t sub_num) -{ - _length_beats = _session.tempo_map().exact_qn_at_sample (_position + _length, sub_num) - quarter_note(); -} - -void -MidiRegion::set_position_internal (timepos_t const & pos, bool allow_bbt_recompute, const int32_t sub_num) -{ - Region::set_position_internal (pos, allow_bbt_recompute, sub_num); - - /* don't clobber _start _length and _length_beats if session loading.*/ - if (_session.loading()) { - return; - } - - /* set _start to new position in tempo map */ - _start = _session.tempo_map().samples_between_quarter_notes (quarter_note() - start_beats(), quarter_note()); - - /* in construction from src */ - if (_length_beats == 0.0) { - update_length_beats (sub_num); - } - - if (position_lock_style() == AudioTime) { - _length_beats = _session.tempo_map().quarter_note_at_sample (_position + _length) - quarter_note(); - } else { - /* leave _length_beats alone, and change _length to reflect the state of things - at the new position (tempo map may dictate a different number of samples). - */ - Region::set_length_internal (_session.tempo_map().samples_between_quarter_notes (quarter_note(), quarter_note() + length_beats()), sub_num); - } -} - -samplecnt_t +timecnt_t MidiRegion::read_at (Evoral::EventSink& out, - samplepos_t position, - samplecnt_t dur, - Evoral::Range* loop_range, - MidiCursor& cursor, - uint32_t chan_n, - NoteMode mode, - MidiStateTracker* tracker, - MidiChannelFilter* filter) const + timepos_t const & position, + timecnt_t const & dur, + Temporal::Range* loop_range, + MidiCursor& cursor, + uint32_t chan_n, + NoteMode mode, + MidiStateTracker* tracker, + MidiChannelFilter* filter) const { return _read_at (_sources, out, position, dur, loop_range, cursor, chan_n, mode, tracker, filter); } -samplecnt_t +timecnt_t MidiRegion::master_read_at (MidiRingBuffer& out, - samplepos_t position, - samplecnt_t dur, - Evoral::Range* loop_range, - MidiCursor& cursor, - uint32_t chan_n, - NoteMode mode) const + timepos_t const & position, + timecnt_t const & dur, + Temporal::Range* loop_range, + MidiCursor& cursor, + uint32_t chan_n, + NoteMode mode) const { return _read_at (_master_sources, out, position, dur, loop_range, cursor, chan_n, mode); /* no tracker */ } -samplecnt_t +timecnt_t MidiRegion::_read_at (const SourceList& /*srcs*/, Evoral::EventSink& dst, - samplepos_t position, - samplecnt_t dur, - Evoral::Range* loop_range, - MidiCursor& cursor, - uint32_t chan_n, - NoteMode mode, - MidiStateTracker* tracker, - MidiChannelFilter* filter) const + timepos_t const & position, + timecnt_t const & xdur, + Temporal::Range* loop_range, + MidiCursor& cursor, + uint32_t chan_n, + NoteMode mode, + MidiStateTracker* tracker, + MidiChannelFilter* filter) const { - sampleoffset_t internal_offset = 0; - samplecnt_t to_read = 0; + timecnt_t dur (xdur); + timecnt_t internal_offset; + timecnt_t to_read; /* precondition: caller has verified that we cover the desired section */ assert(chan_n == 0); if (muted()) { - return 0; /* read nothing */ + return timecnt_t(); /* read nothing */ } if (position < _position) { /* we are starting the read from before the start of the region */ internal_offset = 0; - dur -= _position - position; + dur -= position.distance (_position); } else { /* we are starting the read from after the start of the region */ - internal_offset = position - _position; + internal_offset = _position.val().distance (position); } if (internal_offset >= _length) { - return 0; /* read nothing */ + return timecnt_t(); /* read nothing */ } if ((to_read = min (dur, _length - internal_offset)) == 0) { - return 0; /* read nothing */ + return timecnt_t(); /* read nothing */ } boost::shared_ptr src = midi_source(chan_n); @@ -416,18 +263,16 @@ MidiRegion::_read_at (const SourceList& /*srcs*/, if (src->midi_read ( lm, // source lock dst, // destination buffer - _position - _start, // start position of the source in session samples - _start + internal_offset, // where to start reading in the source + _position.val().earlier (_start.val()), // start position of the source on timeline + _start.val() + internal_offset, // where to start reading in the source to_read, // read duration in samples loop_range, cursor, tracker, filter, - _filtered_parameters, - quarter_note(), - _start_beats + _filtered_parameters ) != to_read) { - return 0; /* "read nothing" */ + return timecnt_t(); /* "read nothing" */ } return to_read; @@ -440,7 +285,7 @@ MidiRegion::render (Evoral::EventSink& dst, NoteMode mode, MidiChannelFilter* filter) const { - sampleoffset_t internal_offset = 0; + timecnt_t internal_offset; /* precondition: caller has verified that we cover the desired section */ @@ -453,12 +298,12 @@ MidiRegion::render (Evoral::EventSink& dst, /* dump pulls from zero to infinity ... */ - if (_position) { + if (!_position.val().zero()) { /* we are starting the read from before the start of the region */ internal_offset = 0; } else { /* we are starting the read from after the start of the region */ - internal_offset = -_position; + internal_offset = timecnt_t (-_position.val()); } if (internal_offset >= _length) { @@ -492,22 +337,21 @@ MidiRegion::render (Evoral::EventSink& dst, src->midi_read ( lm, // source lock dst, // destination buffer - _position - _start, // start position of the source in session samples - _start + internal_offset, // where to start reading in the source + this->source_position(), // start position of the source in session samples + this->nt_start() + internal_offset, // where to start reading in the source _length, // length to read 0, cursor, &tracker, filter, - _filtered_parameters, - quarter_note(), - _start_beats); + _filtered_parameters); /* resolve any notes that were "cut off" by the end of the region. The * Note-Off's get inserted at the end of the region */ - tracker.resolve_notes (dst, (_position - _start) + (_start + internal_offset + _length)); + const timepos_t end = source_position() + nt_start() + internal_offset + nt_length(); + tracker.resolve_notes (dst, end.samples()); return 0; } @@ -639,7 +483,7 @@ MidiRegion::model_contents_changed () } void -MidiRegion::model_shifted (double qn_distance) +MidiRegion::model_shifted (timecnt_t distance) { if (!model()) { return; @@ -647,11 +491,8 @@ MidiRegion::model_shifted (double qn_distance) if (!_ignore_shift) { PropertyChange what_changed; - _start_beats += qn_distance; - samplepos_t const new_start = _session.tempo_map().samples_between_quarter_notes (_quarter_note - _start_beats, _quarter_note); - _start = new_start; + _start += distance; what_changed.add (Properties::start); - what_changed.add (Properties::start_beats); what_changed.add (Properties::contents); send_change (what_changed); } else { @@ -690,90 +531,11 @@ MidiRegion::model_automation_state_changed (Evoral::Parameter const & p) void MidiRegion::fix_negative_start () { - BeatsSamplesConverter c (_session.tempo_map(), _position); - _ignore_shift = true; - model()->insert_silence_at_start (Temporal::Beats (- _start_beats)); + model()->insert_silence_at_start (-_start.val().beats()); - _start = 0; - _start_beats = 0.0; -} - -void -MidiRegion::set_start_internal (samplecnt_t s, const int32_t sub_num) -{ - Region::set_start_internal (s, sub_num); - - set_start_beats_from_start_samples (); -} - -void -MidiRegion::trim_to_internal (timepos_t const & position, samplecnt_t length, const int32_t sub_num) -{ - if (locked()) { - return; - } - - PropertyChange what_changed; - - - /* Set position before length, otherwise for MIDI regions this bad thing happens: - * 1. we call set_length_internal; length in beats is computed using the region's current - * (soon-to-be old) position - * 2. we call set_position_internal; position is set and length in samples re-computed using - * length in beats from (1) but at the new position, which is wrong if the region - * straddles a tempo/meter change. - */ - - if (_position != position) { - - const double pos_qn = _session.tempo_map().exact_qn_at_sample (position, sub_num); - const double old_pos_qn = quarter_note(); - - /* sets _pulse to new position.*/ - set_position_internal (position, true, sub_num); - what_changed.add (Properties::position); - - double new_start_qn = start_beats() + (pos_qn - old_pos_qn); - samplepos_t new_start = _session.tempo_map().samples_between_quarter_notes (pos_qn - new_start_qn, pos_qn); - - if (!verify_start_and_length (new_start, length)) { - return; - } - - _start_beats = new_start_qn; - what_changed.add (Properties::start_beats); - - set_start_internal (new_start, sub_num); - what_changed.add (Properties::start); - } - - if (_length != length) { - - if (!verify_start_and_length (_start, length)) { - return; - } - - set_length_internal (length, sub_num); - what_changed.add (Properties::length); - what_changed.add (Properties::length_beats); - } - - set_whole_file (false); - - PropertyChange start_and_length; - - start_and_length.add (Properties::start); - start_and_length.add (Properties::length); - - if (what_changed.contains (start_and_length)) { - first_edit (); - } - - if (!what_changed.empty()) { - send_change (what_changed); - } + _start = timecnt_t::zero_at (_start.val().time_domain(), nt_position()); } bool diff --git a/libs/ardour/midi_scene_changer.cc b/libs/ardour/midi_scene_changer.cc index ceed80f3b4..b0bad8cf7c 100644 --- a/libs/ardour/midi_scene_changer.cc +++ b/libs/ardour/midi_scene_changer.cc @@ -87,7 +87,7 @@ MIDISceneChanger::gather (const Locations::LocationList& locations) have_seen_bank_changes = true; } - scenes.insert (std::make_pair ((*l)->start(), msc)); + scenes.insert (std::make_pair ((*l)->start_sample(), msc)); } } } @@ -314,7 +314,7 @@ MIDISceneChanger::program_change_input (MIDI::Parser& parser, MIDI::byte program return; } - loc = new Location (_session, time, time, new_name, Location::IsMark, 0); + loc = new Location (_session, timepos_t (time), timepos_t (time), new_name, Location::IsMark); new_mark = true; } @@ -356,7 +356,7 @@ MIDISceneChanger::jump_to (int bank, int program) { const Locations::LocationList& locations (_session.locations()->list()); boost::shared_ptr sc; - samplepos_t where = max_samplepos; + timepos_t where = timepos_t::max (Temporal::AudioTime); for (Locations::LocationList::const_iterator l = locations.begin(); l != locations.end(); ++l) { @@ -370,7 +370,7 @@ MIDISceneChanger::jump_to (int bank, int program) } } - if (where != max_samplepos) { - _session.request_locate (where); + if (where != timepos_t::max (Temporal::AudioTime)) { + _session.request_locate (where.samples()); } } diff --git a/libs/ardour/midi_source.cc b/libs/ardour/midi_source.cc index cd952ef8a3..4ed485355c 100644 --- a/libs/ardour/midi_source.cc +++ b/libs/ardour/midi_source.cc @@ -168,65 +168,36 @@ MidiSource::set_state (const XMLNode& node, int /*version*/) return 0; } -bool -MidiSource::empty () const -{ - return !_length_beats; -} - -samplecnt_t -MidiSource::length (samplepos_t pos) const -{ - if (!_length_beats) { - return 0; - } - - BeatsSamplesConverter converter(_session.tempo_map(), pos); - return converter.to(_length_beats); -} - -void -MidiSource::update_length (samplecnt_t) -{ - // You're not the boss of me! -} - void MidiSource::invalidate (const Lock& lock) { Invalidated(_session.transport_rolling()); } -samplecnt_t +timecnt_t MidiSource::midi_read (const Lock& lm, Evoral::EventSink& dst, - samplepos_t source_start, - samplepos_t start, - samplecnt_t cnt, - Evoral::Range* loop_range, + timepos_t const & source_start, + timecnt_t const & start, + timecnt_t const & cnt, + Temporal::Range* loop_range, MidiCursor& cursor, MidiStateTracker* tracker, MidiChannelFilter* filter, - const std::set& filtered, - const double pos_beats, - const double start_beats) const + const std::set& filtered) { - BeatsSamplesConverter converter(_session.tempo_map(), source_start); - - const double start_qn = pos_beats - start_beats; - DEBUG_TRACE (DEBUG::MidiSourceIO, string_compose ("MidiSource::midi_read() %5 sstart %1 start %2 cnt %3 tracker %4\n", source_start, start, cnt, tracker, name())); if (!_model) { - return read_unlocked (lm, dst, source_start, start, cnt, loop_range, tracker, filter); + return timecnt_t (read_unlocked (lm, dst, source_start, start, cnt, loop_range, tracker, filter), start.position()); } // Find appropriate model iterator - Evoral::Sequence::const_iterator& i = cursor.iter; + const bool linear_read = cursor.last_read_end != 0 && start == cursor.last_read_end; - if (!linear_read || !i.valid()) { + if (!linear_read || !cursor.iter.valid()) { /* Cached iterator is invalid, search for the first event past start. Note that multiple tracks can use a MidiSource simultaneously, so all playback state must be in parameters (the cursor) and must not @@ -234,64 +205,76 @@ MidiSource::midi_read (const Lock& lm, See http://tracker.ardour.org/view.php?id=6541 */ cursor.connect(Invalidated); - cursor.iter = _model->begin(converter.from(start), false, filtered, &cursor.active_notes); + cursor.iter = _model->begin (start.beats(), false, filtered, &cursor.active_notes); cursor.active_notes.clear(); } cursor.last_read_end = start + cnt; + // Find appropriate model iterator + Evoral::Sequence::const_iterator& i = cursor.iter; + // Copy events in [start, start + cnt) into dst + + const Temporal::Beats source_start_beats = source_start.beats(); + const Temporal::Beats region_start_beats = start.beats(); + const Temporal::Beats cnt_beats = cnt.beats (); + + const Temporal::Beats end = source_start_beats + region_start_beats + cnt_beats; + const Temporal::Beats session_source_start = (source_start + start).beats(); + for (; i != _model->end(); ++i) { // Offset by source start to convert event time to session time - samplepos_t time_samples = _session.tempo_map().sample_at_quarter_note (i->time().to_double() + start_qn); + const Temporal::Beats session_event_beats = source_start_beats + i->time(); - if (time_samples < start + source_start) { + if (session_event_beats < session_source_start) { /* event too early */ - + DEBUG_TRACE (DEBUG::MidiSourceIO, string_compose ("%1: skip event, too early @ %2 for %3\n", _name, session_event_beats, session_source_start)); continue; - } else if (time_samples >= start + cnt + source_start) { + } else if (session_event_beats >= end) { - DEBUG_TRACE (DEBUG::MidiSourceIO, - string_compose ("%1: reached end with event @ %2 vs. %3\n", - _name, time_samples, start+cnt)); + DEBUG_TRACE (DEBUG::MidiSourceIO, string_compose ("%1: reached end (%2) with event @ %3\n", _name, end, session_event_beats)); break; } else { /* in range */ + timepos_t seb = timepos_t (session_event_beats); + samplepos_t time_samples = seb.samples(); + if (loop_range) { - time_samples = loop_range->squish (time_samples); + time_samples = loop_range->squish (seb).samples(); } const uint8_t status = i->buffer()[0]; const bool is_channel_event = (0x80 <= (status & 0xF0)) && (status <= 0xE0); + if (filter && is_channel_event) { /* Copy event so the filter can modify the channel. I'm not - sure if this is necessary here (channels are mapped later in - buffers anyway), but it preserves existing behaviour without - destroying events in the model during read. */ + * sure if this is necessary here (channels are mapped later in + * buffers anyway), but it preserves existing behaviour without + * destroying events in the model during read. + */ Evoral::Event ev(*i, true); + if (!filter->filter(ev.buffer(), ev.size())) { dst.write (time_samples, ev.event_type(), ev.size(), ev.buffer()); } else { - DEBUG_TRACE (DEBUG::MidiSourceIO, - string_compose ("%1: filter event @ %2 type %3 size %4\n", - _name, time_samples, i->event_type(), i->size())); + DEBUG_TRACE (DEBUG::MidiSourceIO, string_compose ("%1: filter event @ %2 type %3 size %4\n", _name, time_samples, i->event_type(), i->size())); } } else { dst.write (time_samples, i->event_type(), i->size(), i->buffer()); } + #ifndef NDEBUG if (DEBUG_ENABLED(DEBUG::MidiSourceIO)) { DEBUG_STR_DECL(a); - DEBUG_STR_APPEND(a, string_compose ("%1 added event @ %2 sz %3 within %4 .. %5 ", - _name, time_samples, i->size(), - start + source_start, start + cnt + source_start)); + DEBUG_STR_APPEND(a, string_compose ("%1 added event @ %2 (%3) sz %4 within %5 .. %6 ", _name, time_samples, session_event_beats, i->size(), source_start + start, end)); for (size_t n=0; n < i->size(); ++n) { DEBUG_STR_APPEND(a,hex); DEBUG_STR_APPEND(a,"0x"); @@ -312,18 +295,18 @@ MidiSource::midi_read (const Lock& lm, return cnt; } -samplecnt_t +timecnt_t MidiSource::midi_write (const Lock& lm, MidiRingBuffer& source, - samplepos_t source_start, - samplecnt_t cnt) + timepos_t const & source_start, + timecnt_t const & cnt) { - const samplecnt_t ret = write_unlocked (lm, source, source_start, cnt); + const timecnt_t ret = write_unlocked (lm, source, source_start, cnt); - if (cnt == max_samplecnt) { + if (cnt == std::numeric_limits::max()) { invalidate(lm); } else { - _capture_length += cnt; + _capture_length += cnt.samples(); } return ret; @@ -356,13 +339,15 @@ MidiSource::mark_write_starting_now (samplecnt_t position, because it is not RT-safe. */ - set_natural_position (position); +#warning NUTEMPO QUESTION should the time domain here reflect some setting for this source? + set_natural_position (timepos_t (position)); _capture_length = capture_length; _capture_loop_length = loop_length; - TempoMap& map (_session.tempo_map()); - BeatsSamplesConverter converter(map, position); - _length_beats = converter.from(capture_length); +#warning NUTEMPO FIXME needs session to use tempo map + //TempoMap& map (_session.tempo_map()); + //BeatsSamplesConverter converter(map, position); + //_length_beats = converter.from(capture_length); } void diff --git a/libs/ardour/midi_stretch.cc b/libs/ardour/midi_stretch.cc index a250e9b869..c44e283386 100644 --- a/libs/ardour/midi_stretch.cc +++ b/libs/ardour/midi_stretch.cc @@ -55,21 +55,7 @@ MidiStretch::run (boost::shared_ptr r, Progress*) return -1; } - const TempoMap& tmap (session.tempo_map ()); - - /* Fraction is based on sample-time, while MIDI source - * is always using music-time. This matters in case there is - * a tempo-ramp. So we need to scale the ratio to music-time */ - const double mtfrac = - tmap.framewalk_to_qn (region->position (), region->length () * _request.time_fraction).to_double () - / - tmap.framewalk_to_qn (region->position (), region->length ()).to_double (); - - /* the name doesn't need to be super-precise, but allow for 2 fractional - * digits just to disambiguate close but not identical stretches. - */ - - snprintf (suffix, sizeof (suffix), "@%d", (int) floor (mtfrac * 100.0f)); + snprintf (suffix, sizeof (suffix), "@%d", (int) floor ((_request.time_fraction.numerator()/ (double) _request.time_fraction.denominator()) * 100.0f)); string new_name = region->name(); string::size_type at = new_name.find ('@'); @@ -107,9 +93,6 @@ MidiStretch::run (boost::shared_ptr r, Progress*) boost::shared_ptr new_model = new_src->model(); new_model->start_write(); - const double r_start = tmap.quarter_notes_between_samples (region->position () - region->start (), region->position ()); - const double r_end = r_start + tmap.quarter_notes_between_samples (region->position (), region->position () + region->length ()); - #ifdef DEBUG_MIDI_STRETCH printf ("stretch start: %f end: %f [* %f] * %f\n", r_start, r_end, _request.time_fraction, mtfrac); #endif @@ -119,26 +102,7 @@ MidiStretch::run (boost::shared_ptr r, Progress*) */ for (Evoral::Sequence::const_iterator i = old_model->begin (MidiModel::TimeType(), true); i != old_model->end(); ++i) { - if (i->time() < r_start) { -#ifdef DEBUG_MIDI_STRETCH - cout << "SKIP EARLY EVENT " << i->time() << "\n"; -#endif - continue; - } - if (i->time() > r_end) { -#ifdef DEBUG_MIDI_STRETCH - cout << "SKIP LATE EVENT " << i->time() << "\n"; - continue; -#else - break; -#endif - } - -#ifdef DEBUG_MIDI_STRETCH - cout << "STRETCH " << i->time() << " OFFSET FROM START @ " << r_start << " = " << (i->time() - r_start) << " TO " << (i->time() - r_start) * mtfrac << "\n"; -#endif - - const MidiModel::TimeType new_time = (i->time() - r_start) * mtfrac; + const MidiModel::TimeType new_time = i->time().operator* (_request.time_fraction); // FIXME: double copy Evoral::Event ev(*i, true); @@ -154,9 +118,8 @@ MidiStretch::run (boost::shared_ptr r, Progress*) const int ret = finish (region, nsrcs, new_name); /* non-musical */ - results[0]->set_start(0); - results[0]->set_position (r->position ()); // force updates the region's quarter-note position - results[0]->set_length((samplecnt_t) floor (r->length() * _request.time_fraction), 0); +#warning NUTEMPO FIXME do we still need this? + results[0]->set_length (r->nt_length().operator* ( _request.time_fraction)); return ret; } diff --git a/libs/ardour/midi_track.cc b/libs/ardour/midi_track.cc index f78cb385b9..7098ee3a90 100644 --- a/libs/ardour/midi_track.cc +++ b/libs/ardour/midi_track.cc @@ -370,8 +370,8 @@ MidiTrack::update_controls (BufferSet const& bufs) const Evoral::Parameter param = midi_parameter(ev.buffer(), ev.size()); const boost::shared_ptr control = automation_control (param); if (control) { - double old = control->get_double (false, 0); - control->set_double (ev.value(), 0, false); + double old = control->get_double (false, timepos_t::zero (true)); + control->set_double (ev.value(), timepos_t::zero (false), false); if (old != ev.value()) { control->Changed (false, Controllable::NoGroup); } @@ -406,9 +406,11 @@ MidiTrack::realtime_locate (bool for_loop_end) } void -MidiTrack::non_realtime_locate (samplepos_t pos) +MidiTrack::non_realtime_locate (samplepos_t spos) { - Track::non_realtime_locate(pos); + timepos_t pos (spos); + + Track::non_realtime_locate (spos); boost::shared_ptr playlist = _disk_writer->midi_playlist(); if (!playlist) { @@ -416,7 +418,7 @@ MidiTrack::non_realtime_locate (samplepos_t pos) } /* Get the top unmuted region at this position. */ - boost::shared_ptr region = boost::dynamic_pointer_cast(playlist->top_unmuted_region_at(pos)); + boost::shared_ptr region = boost::dynamic_pointer_cast (playlist->top_unmuted_region_at (pos)); if (!region) { return; @@ -433,8 +435,7 @@ MidiTrack::non_realtime_locate (samplepos_t pos) } /* Update track controllers based on its "automation". */ - const samplepos_t origin = region->position() - region->start(); - BeatsSamplesConverter bfc(_session.tempo_map(), origin); + const timepos_t pos_beats = timepos_t (region->source_position().distance (pos).beats ()); /* relative to source start */ for (Controls::const_iterator c = _controls.begin(); c != _controls.end(); ++c) { @@ -450,7 +451,7 @@ MidiTrack::non_realtime_locate (samplepos_t pos) if ((tcontrol = boost::dynamic_pointer_cast(c->second)) && (rcontrol = region->control(tcontrol->parameter()))) { - const Temporal::Beats pos_beats = bfc.from(pos - origin); + if (rcontrol->list()->size() > 0) { tcontrol->set_value(rcontrol->list()->eval(pos_beats), Controllable::NoGroup); } diff --git a/libs/ardour/monitor_control.cc b/libs/ardour/monitor_control.cc index 0d0a98ca87..a6bc5988ed 100644 --- a/libs/ardour/monitor_control.cc +++ b/libs/ardour/monitor_control.cc @@ -26,7 +26,7 @@ using namespace PBD; MonitorControl::MonitorControl (Session& session, std::string const & name, Monitorable& m) : SlavableAutomationControl (session, MonitoringAutomation, ParameterDescriptor (MonitoringAutomation), - boost::shared_ptr(new AutomationList(Evoral::Parameter(MonitoringAutomation))), + boost::shared_ptr(new AutomationList(Evoral::Parameter(MonitoringAutomation), Temporal::AudioTime)), name) , _monitorable (m) diff --git a/libs/ardour/mute_control.cc b/libs/ardour/mute_control.cc index aa1de9e8bc..93a2111b3b 100644 --- a/libs/ardour/mute_control.cc +++ b/libs/ardour/mute_control.cc @@ -29,9 +29,10 @@ using namespace ARDOUR; using namespace std; +#warning NUTEMPO QUESTION what time domain shoudl this really use? MuteControl::MuteControl (Session& session, std::string const & name, Muteable& m) : SlavableAutomationControl (session, MuteAutomation, ParameterDescriptor (MuteAutomation), - boost::shared_ptr (new AutomationList (Evoral::Parameter (MuteAutomation))), + boost::shared_ptr (new AutomationList (Evoral::Parameter (MuteAutomation), Temporal::AudioTime)), name) , _muteable (m) { @@ -189,7 +190,7 @@ MuteControl::automation_run (samplepos_t start, pframes_t len) bool mute = false; if (list() && automation_playback()) { - mute = list()->rt_safe_eval (start, valid) >= 0.5; + mute = list()->rt_safe_eval (timepos_t (start), valid) >= 0.5; } if (!valid) { diff --git a/libs/ardour/onset_detector.cc b/libs/ardour/onset_detector.cc index c7a90ac35b..815540b7de 100644 --- a/libs/ardour/onset_detector.cc +++ b/libs/ardour/onset_detector.cc @@ -48,7 +48,7 @@ OnsetDetector::operational_identifier() } int -OnsetDetector::run (const std::string& path, Readable* src, uint32_t channel, AnalysisFeatureList& results) +OnsetDetector::run (const std::string& path, AudioReadable* src, uint32_t channel, AnalysisFeatureList& results) { current_results = &results; int ret = analyse (path, src, channel); diff --git a/libs/ardour/pannable.cc b/libs/ardour/pannable.cc index debdbba2d1..b5255d2fb8 100644 --- a/libs/ardour/pannable.cc +++ b/libs/ardour/pannable.cc @@ -151,7 +151,7 @@ Pannable::set_automation_state (AutoState state) } void -Pannable::start_touch (double when) +Pannable::start_touch (timepos_t const & when) { const Controls& c (controls()); @@ -165,7 +165,7 @@ Pannable::start_touch (double when) } void -Pannable::stop_touch (double when) +Pannable::stop_touch (timepos_t const & when) { const Controls& c (controls()); diff --git a/libs/ardour/phase_control.cc b/libs/ardour/phase_control.cc index bc0a11130c..2c3bc392bb 100644 --- a/libs/ardour/phase_control.cc +++ b/libs/ardour/phase_control.cc @@ -27,7 +27,7 @@ using namespace ARDOUR; PhaseControl::PhaseControl (Session& session, std::string const & name) : AutomationControl (session, PhaseAutomation, ParameterDescriptor (PhaseAutomation), - boost::shared_ptr(new AutomationList(Evoral::Parameter(PhaseAutomation))), + boost::shared_ptr(new AutomationList(Evoral::Parameter(PhaseAutomation), Temporal::AudioTime)), name) { } diff --git a/libs/ardour/playlist.cc b/libs/ardour/playlist.cc index 6111b01529..0cf6cc66a2 100644 --- a/libs/ardour/playlist.cc +++ b/libs/ardour/playlist.cc @@ -184,8 +184,8 @@ Playlist::Playlist (boost::shared_ptr other, string namestr, boo in_set_state++; - for (list >::iterator x = tmp.begin (); x != tmp.end (); ++x) { - add_region_internal ((*x), (*x)->position (), thawlist); + for (list >::iterator x = tmp.begin(); x != tmp.end(); ++x) { + add_region_internal ((*x), (*x)->nt_position(), thawlist); } thawlist.release (); @@ -202,8 +202,8 @@ Playlist::Playlist (boost::shared_ptr other, string namestr, boo _frozen = other->_frozen; } -Playlist::Playlist (boost::shared_ptr other, samplepos_t start, samplecnt_t cnt, string str, bool hide) - : SessionObject (other->_session, str) +Playlist::Playlist (boost::shared_ptr other, timepos_t const & start, timepos_t const & cnt, string str, bool hide) + : SessionObject(other->_session, str) , regions (*this) , _type (other->_type) , _orig_track_id (other->_orig_track_id) @@ -211,7 +211,7 @@ Playlist::Playlist (boost::shared_ptr other, samplepos_t start, { RegionReadLock rlock2 (const_cast (other.get ())); - samplepos_t end = start + cnt - 1; + timepos_t end = timepos_t (start + cnt); init (hide); @@ -221,64 +221,50 @@ Playlist::Playlist (boost::shared_ptr other, samplepos_t start, for (RegionList::const_iterator i = other->regions.begin (); i != other->regions.end (); ++i) { boost::shared_ptr region; boost::shared_ptr new_region; - sampleoffset_t offset = 0; - samplepos_t position = 0; - samplecnt_t len = 0; - string new_name; - Evoral::OverlapType overlap; + timecnt_t offset; + timepos_t position; + timecnt_t len; + string new_name; + Temporal::OverlapType overlap; region = *i; overlap = region->coverage (start, end); switch (overlap) { - case Evoral::OverlapNone: - continue; + case Temporal::OverlapNone: + continue; - case Evoral::OverlapInternal: - offset = start - region->position (); - position = 0; - len = cnt; - break; + case Temporal::OverlapInternal: + offset = region->nt_position().distance (start); + position = 0; + len = timecnt_t (cnt); + break; - case Evoral::OverlapStart: - offset = 0; - position = region->position () - start; - len = end - region->position (); - break; + case Temporal::OverlapStart: + offset = 0; + position = region->source_position(); + len = region->nt_position().distance (end); + break; - case Evoral::OverlapEnd: - offset = start - region->position (); - position = 0; - len = region->length () - offset; - break; + case Temporal::OverlapEnd: + offset = region->nt_position().distance (start); + position = 0; + len = region->nt_length() - offset; + break; - case Evoral::OverlapExternal: - offset = 0; - position = region->position () - start; - len = region->length (); - break; + case Temporal::OverlapExternal: + offset = 0; + position = region->source_position(); + len = region->nt_length(); + break; } RegionFactory::region_name (new_name, region->name (), false); PropertyList plist; - if (_type == DataType::MIDI) { - boost::shared_ptr mregion = boost::dynamic_pointer_cast (region); - if (mregion && offset) { - int32_t division = 1; /*magic value that ignores the meter (right?)*/ - const double start_quarter_note = _session.tempo_map ().exact_qn_at_sample (start, division); - const double start_offset_quarter_note = start_quarter_note - region->quarter_note (); - const double end_samples = (overlap == Evoral::OverlapStart ? end : /*end the new region at the end of the selection*/ - region->position () + region->length () - 1); /*use the region's end*/ - const double length_quarter_note = _session.tempo_map ().exact_qn_at_sample (end_samples, division) - start_quarter_note; - plist.add (Properties::start_beats, mregion->start_beats () + start_offset_quarter_note); - plist.add (Properties::length_beats, length_quarter_note); - } - } - - plist.add (Properties::start, region->start () + offset); + plist.add (Properties::start, region->nt_start() + offset); plist.add (Properties::length, len); plist.add (Properties::name, new_name); plist.add (Properties::layer, region->layer ()); @@ -295,7 +281,8 @@ Playlist::Playlist (boost::shared_ptr other, samplepos_t start, * RippleAll mode) at the end of construction, any length of cnt beyond * the extents of the regions is end_space */ - _end_space = cnt - (get_extent ().second - get_extent ().first); + _end_space = timecnt_t (cnt) - (get_extent().first.distance (get_extent().second)); + in_set_state--; first_set_state = false; @@ -512,13 +499,13 @@ Playlist::notify_region_removed (boost::shared_ptr r) void Playlist::notify_region_moved (boost::shared_ptr r) { - Evoral::RangeMove const move (r->last_position (), r->length (), r->position ()); + Temporal::RangeMove move (r->nt_last (), r->nt_length (), r->nt_position ()); if (holding_state ()) { pending_range_moves.push_back (move); } else { - list > m; + list m; m.push_back (move); RangesMoved (m, false); } @@ -527,18 +514,18 @@ Playlist::notify_region_moved (boost::shared_ptr r) void Playlist::notify_region_start_trimmed (boost::shared_ptr r) { - if (r->position () >= r->last_position ()) { + if (r->nt_position() >= r->last_position()) { /* trimmed shorter */ return; } - Evoral::Range const extra (r->position (), r->last_position ()); + Temporal::Range const extra (r->nt_position(), r->last_position()); if (holding_state ()) { pending_region_extensions.push_back (extra); } else { - list > r; + list r; r.push_back (extra); RegionsExtended (r); } @@ -547,17 +534,17 @@ Playlist::notify_region_start_trimmed (boost::shared_ptr r) void Playlist::notify_region_end_trimmed (boost::shared_ptr r) { - if (r->length () < r->last_length ()) { + if (r->nt_length() < r->last_length()) { /* trimmed shorter */ } - Evoral::Range const extra (r->position () + r->last_length (), r->position () + r->length ()); + Temporal::Range const extra (r->nt_position() + r->last_length(), r->nt_position() + r->nt_length()); if (holding_state ()) { pending_region_extensions.push_back (extra); } else { - list > r; + list r; r.push_back (extra); RegionsExtended (r); } @@ -609,7 +596,10 @@ Playlist::flush_notifications (bool from_undo) * model, sort them by existing layer, then timestamp them. */ - list > crossfade_ranges; + // RegionSortByLayer cmp; + // pending_bounds.sort (cmp); + + list crossfade_ranges; for (RegionList::iterator r = pending_bounds.begin (); r != pending_bounds.end (); ++r) { crossfade_ranges.push_back ((*r)->last_range ()); @@ -690,26 +680,26 @@ Playlist::clear_pending () /** Note: this calls set_layer (..., DBL_MAX) so it will reset the layering index of region */ void -Playlist::add_region (boost::shared_ptr region, samplepos_t position, float times, bool auto_partition, int32_t sub_num, double quarter_note, bool for_music) +Playlist::add_region (boost::shared_ptr region, timepos_t const & position, float times, bool auto_partition) { RegionWriteLock rlock (this); times = fabs (times); int itimes = (int)floor (times); - samplepos_t pos = position; + timepos_t pos = position; if (times == 1 && auto_partition) { - partition_internal (pos - 1, (pos + region->length ()), true, rlock.thawlist); + partition_internal (pos - 1, (pos + region->nt_length ()), true, rlock.thawlist); for (RegionList::iterator i = rlock.thawlist.begin (); i != rlock.thawlist.end (); ++i) { _session.add_command (new StatefulDiffCommand (*i)); } } if (itimes >= 1) { - add_region_internal (region, pos, rlock.thawlist, sub_num, quarter_note, for_music); + add_region_internal (region, pos, rlock.thawlist); set_layer (region, DBL_MAX); - pos += region->length (); + pos += region->nt_length(); --itimes; } @@ -719,28 +709,29 @@ Playlist::add_region (boost::shared_ptr region, samplepos_t position, fl for (int i = 0; i < itimes; ++i) { boost::shared_ptr copy = RegionFactory::create (region, true, false, &rlock.thawlist); - add_region_internal (copy, pos, rlock.thawlist, sub_num); + add_region_internal (copy, pos, rlock.thawlist); set_layer (copy, DBL_MAX); - pos += region->length (); + pos += region->nt_length(); } - samplecnt_t length = 0; + timecnt_t length; if (floor (times) != times) { - length = (samplecnt_t)floor (region->length () * (times - floor (times))); + length = region->nt_length() * (times - floor (times)); string name; RegionFactory::region_name (name, region->name (), false); { PropertyList plist; - plist.add (Properties::start, region->start ()); + plist.add (Properties::start, region->nt_start()); plist.add (Properties::length, length); plist.add (Properties::name, name); plist.add (Properties::layer, region->layer ()); boost::shared_ptr sub = RegionFactory::create (region, plist, true, &rlock.thawlist); - add_region_internal (sub, pos, rlock.thawlist, sub_num); + add_region_internal (sub, pos, rlock.thawlist); + set_layer (sub, DBL_MAX); } } @@ -759,7 +750,7 @@ Playlist::set_region_ownership () } bool -Playlist::add_region_internal (boost::shared_ptr region, samplepos_t position, ThawList& thawlist, int32_t sub_num, double quarter_note, bool for_music) +Playlist::add_region_internal (boost::shared_ptr region, timepos_t const & position, Thawlist& thawlist) { if (region->data_type () != _type) { return false; @@ -777,16 +768,16 @@ Playlist::add_region_internal (boost::shared_ptr region, samplepos_t pos region->set_playlist (boost::weak_ptr (foo)); } - if (for_music) { -#warning NUTEMPO FIXME need timepos_t here - region->set_position_music (quarter_note); - } else { - region->set_position (position, sub_num); - } + region->set_position (position); regions.insert (upper_bound (regions.begin (), regions.end (), region, cmp), region); all_regions.insert (region); +<<<<<<< HEAD +======= + possibly_splice_unlocked (position, region->nt_length(), region, thawlist); + +>>>>>>> 42145ee744 (libardour: conversion to use timeline types (mega-commit)) if (!holding_state ()) { /* layers get assigned from XML state, and are not reset during undo/redo */ relayer (); @@ -809,13 +800,20 @@ Playlist::add_region_internal (boost::shared_ptr region, samplepos_t pos } void -Playlist::replace_region (boost::shared_ptr old, boost::shared_ptr newr, samplepos_t pos) +Playlist::replace_region (boost::shared_ptr old, boost::shared_ptr newr, timepos_t const & pos) { RegionWriteLock rlock (this); remove_region_internal (old, rlock.thawlist); add_region_internal (newr, pos, rlock.thawlist); set_layer (newr, old->layer ()); +<<<<<<< HEAD +======= + + _splicing = old_sp; + + possibly_splice_unlocked (pos, old->nt_length() - newr->nt_length(), boost::shared_ptr(), rlock.thawlist); +>>>>>>> 42145ee744 (libardour: conversion to use timeline types (mega-commit)) } void @@ -839,8 +837,8 @@ Playlist::remove_region_internal (boost::shared_ptr region, ThawList& th for (i = regions.begin (); i != regions.end (); ++i) { if (*i == region) { - samplepos_t pos = (*i)->position (); - samplecnt_t distance = (*i)->length (); + timepos_t pos = (*i)->nt_position(); + timecnt_t distance = (*i)->nt_length(); regions.erase (i); @@ -943,43 +941,28 @@ Playlist::get_equivalent_regions (boost::shared_ptr other, vector Region::set_position() -> MidiRegion::set_position_internal() - */ -static void -maybe_add_start_beats (TempoMap const& tm, PropertyList& plist, boost::shared_ptr r, samplepos_t start, samplepos_t end) -{ - boost::shared_ptr mr = boost::dynamic_pointer_cast (r); - if (!mr) { - return; - } - double delta_beats = tm.quarter_notes_between_samples (start, end); - plist.add (Properties::start_beats, mr->start_beats () + delta_beats); -} - /** Go through each region on the playlist and cut them at start and end, removing the section between * start and end if cutting == true. Regions that lie entirely within start and end are always * removed. */ void -Playlist::partition_internal (samplepos_t start, samplepos_t end, bool cutting, ThawList& thawlist) +Playlist::partition_internal (timepos_t const & start, timepos_t const & end, bool cutting, ThawList& thawlist) { RegionList new_regions; { boost::shared_ptr region; boost::shared_ptr current; - string new_name; - RegionList::iterator tmp; - Evoral::OverlapType overlap; - samplepos_t pos1, pos2, pos3, pos4; + string new_name; + RegionList::iterator tmp; + Temporal::OverlapType overlap; + timepos_t pos1, pos2, pos3, pos4; in_partition = true; @@ -995,7 +978,8 @@ Playlist::partition_internal (samplepos_t start, samplepos_t end, bool cutting, current = *i; - if (current->first_sample () >= start && current->last_sample () < end) { + if (start < current->nt_position() && end >= current->nt_last()) { + if (cutting) { remove_region_internal (current, thawlist); } @@ -1008,20 +992,20 @@ Playlist::partition_internal (samplepos_t start, samplepos_t end, bool cutting, * so catch this special case. */ - if (current->first_sample () >= end) { + if (end < current->nt_position()) { continue; } - if ((overlap = current->coverage (start, end)) == Evoral::OverlapNone) { + if ((overlap = current->coverage (start, end)) == Temporal::OverlapNone) { continue; } - pos1 = current->position (); + pos1 = current->nt_position(); pos2 = start; pos3 = end; - pos4 = current->last_sample (); + pos4 = current->nt_last (); - if (overlap == Evoral::OverlapInternal) { + if (overlap == Temporal::OverlapInternal) { /* split: we need 3 new regions, the front, middle and end. * cut: we need 2 regions, the front and end. * @@ -1042,20 +1026,19 @@ Playlist::partition_internal (samplepos_t start, samplepos_t end, bool cutting, PropertyList plist; - plist.add (Properties::start, current->start () + (pos2 - pos1)); - plist.add (Properties::length, pos3 - pos2); + plist.add (Properties::start, current->nt_start() + pos1.distance (pos2)); + plist.add (Properties::length, pos2.distance (pos3)); plist.add (Properties::name, new_name); plist.add (Properties::layer, current->layer ()); plist.add (Properties::layering_index, current->layering_index ()); plist.add (Properties::automatic, true); plist.add (Properties::left_of_split, true); plist.add (Properties::right_of_split, true); - maybe_add_start_beats (_session.tempo_map (), plist, current, current->start (), current->start () + (pos2 - pos1)); /* see note in :_split_region() * for MusicSample is needed to offset region-gain */ - region = RegionFactory::create (current, MusicSample (pos2 - pos1, 0), plist, true, &thawlist); + region = RegionFactory::create (current, pos1.distance (pos1), plist, true, &thawlist); add_region_internal (region, start, thawlist); new_regions.push_back (region); } @@ -1066,16 +1049,15 @@ Playlist::partition_internal (samplepos_t start, samplepos_t end, bool cutting, PropertyList plist; - plist.add (Properties::start, current->start () + (pos3 - pos1)); - plist.add (Properties::length, pos4 - pos3); + plist.add (Properties::start, current->nt_start() + pos1.distance (pos3)); + plist.add (Properties::length, pos3.distance (pos4)); plist.add (Properties::name, new_name); plist.add (Properties::layer, current->layer ()); plist.add (Properties::layering_index, current->layering_index ()); plist.add (Properties::automatic, true); plist.add (Properties::right_of_split, true); - maybe_add_start_beats (_session.tempo_map (), plist, current, current->start (), current->start () + (pos3 - pos1)); - region = RegionFactory::create (current, MusicSample (pos3 - pos1, 0), plist, true, &thawlist); + region = RegionFactory::create (current, pos1.distance (pos3), plist, true, &thawlist ); add_region_internal (region, end, thawlist); new_regions.push_back (region); @@ -1084,9 +1066,10 @@ Playlist::partition_internal (samplepos_t start, samplepos_t end, bool cutting, current->clear_changes (); thawlist.add (current); - current->cut_end (pos2 - 1); + current->cut_end (pos2.decrement()); + + } else if (overlap == Temporal::OverlapEnd) { - } else if (overlap == Evoral::OverlapEnd) { /* * start end * ---------------*************************------------ @@ -1104,16 +1087,15 @@ Playlist::partition_internal (samplepos_t start, samplepos_t end, bool cutting, PropertyList plist; - plist.add (Properties::start, current->start () + (pos2 - pos1)); - plist.add (Properties::length, pos4 - pos2); + plist.add (Properties::start, current->nt_start() + pos1.distance (pos2)); + plist.add (Properties::length, pos2.distance (pos4)); plist.add (Properties::name, new_name); plist.add (Properties::layer, current->layer ()); plist.add (Properties::layering_index, current->layering_index ()); plist.add (Properties::automatic, true); plist.add (Properties::left_of_split, true); - maybe_add_start_beats (_session.tempo_map (), plist, current, current->start (), current->start () + (pos2 - pos1)); - region = RegionFactory::create (current, MusicSample (pos2 - pos1, 0), plist, true, &thawlist); + region = RegionFactory::create (current, pos1.distance (pos2), plist, true, &thawlist); add_region_internal (region, start, thawlist); new_regions.push_back (region); @@ -1123,9 +1105,10 @@ Playlist::partition_internal (samplepos_t start, samplepos_t end, bool cutting, current->clear_changes (); thawlist.add (current); - current->cut_end (pos2 - 1); + current->cut_end (pos2.decrement()); + + } else if (overlap == Temporal::OverlapStart) { - } else if (overlap == Evoral::OverlapStart) { /* split: we need 2 regions: the front and the end. * cut: just trim current to skip the cut area * @@ -1146,14 +1129,13 @@ Playlist::partition_internal (samplepos_t start, samplepos_t end, bool cutting, PropertyList plist; - plist.add (Properties::start, current->start ()); - plist.add (Properties::length, pos3 - pos1); + plist.add (Properties::start, current->nt_start()); + plist.add (Properties::length, pos1.distance (pos3)); plist.add (Properties::name, new_name); plist.add (Properties::layer, current->layer ()); plist.add (Properties::layering_index, current->layering_index ()); plist.add (Properties::automatic, true); plist.add (Properties::right_of_split, true); - maybe_add_start_beats (_session.tempo_map (), plist, current, current->start (), current->start ()); region = RegionFactory::create (current, plist, true, &thawlist); @@ -1166,7 +1148,9 @@ Playlist::partition_internal (samplepos_t start, samplepos_t end, bool cutting, current->clear_changes (); thawlist.add (current); current->trim_front (pos3); - } else if (overlap == Evoral::OverlapExternal) { + + } else if (overlap == Temporal::OverlapExternal) { + /* split: no split required. * cut: remove the region. * @@ -1195,45 +1179,28 @@ Playlist::partition_internal (samplepos_t start, samplepos_t end, bool cutting, } /* keep track of any dead space at end (for pasting into Ripple or RippleAll mode) */ - samplepos_t wanted_length = end - start; - _end_space = wanted_length - _get_extent ().second - _get_extent ().first; + const timecnt_t wanted_length = start.distance (end); + _end_space = wanted_length - _get_extent().first.distance (_get_extent().second); } boost::shared_ptr -Playlist::cut_copy (boost::shared_ptr (Playlist::*pmf) (samplepos_t, samplecnt_t, bool), list& ranges, bool result_is_hidden) +Playlist::cut_copy (boost::shared_ptr (Playlist::*pmf)(timepos_t const &, timecnt_t const &,bool), list& ranges, bool result_is_hidden) { boost::shared_ptr ret; boost::shared_ptr pl; - samplepos_t start; + timepos_t start; if (ranges.empty ()) { return boost::shared_ptr (); } -<<<<<<< HEAD - start = ranges.front ().start; -======= start = ranges.front().start; -<<<<<<< HEAD for (list::iterator i = ranges.begin(); i != ranges.end(); ++i) { pl = (this->*pmf)((*i).start, (*i).length(), result_is_hidden); -======= - - for (list::iterator i = ranges.begin(); i != ranges.end(); ++i) { ->>>>>>> 0bbe6796b9 (Revert "NO-OP: code formatting and cleanup, thanks clang-format") - - for (list::iterator i = ranges.begin (); i != ranges.end (); ++i) { - pl = (this->*pmf) ((*i).start, (*i).length (), result_is_hidden); - -<<<<<<< HEAD if (i == ranges.begin ()) { -======= ->>>>>>> Revert "NO-OP: code formatting and cleanup, thanks clang-format" - if (i == ranges.begin()) { ->>>>>>> 0bbe6796b9 (Revert "NO-OP: code formatting and cleanup, thanks clang-format") ret = pl; } else { /* paste the next section into the nascent playlist, @@ -1241,7 +1208,7 @@ Playlist::cut_copy (boost::shared_ptr (Playlist::*pmf) (samplepos_t, s * chopped. */ - ret->paste (pl, (*i).start - start, 1.0f, 0); + ret->paste (pl, (*i).start().earlier (timecnt_t (start, start)), 1.0f); } } @@ -1249,21 +1216,21 @@ Playlist::cut_copy (boost::shared_ptr (Playlist::*pmf) (samplepos_t, s } boost::shared_ptr -Playlist::cut (list& ranges, bool result_is_hidden) +Playlist::cut (list& ranges, bool result_is_hidden) { boost::shared_ptr (Playlist::*pmf) (samplepos_t, samplecnt_t, bool) = &Playlist::cut; return cut_copy (pmf, ranges, result_is_hidden); } boost::shared_ptr -Playlist::copy (list& ranges, bool result_is_hidden) +Playlist::copy (list& ranges, bool result_is_hidden) { boost::shared_ptr (Playlist::*pmf) (samplepos_t, samplecnt_t, bool) = &Playlist::copy; return cut_copy (pmf, ranges, result_is_hidden); } boost::shared_ptr -Playlist::cut (samplepos_t start, samplecnt_t cnt, bool result_is_hidden) +Playlist::cut (timepos_t const & start, timecnt_t const & cnt, bool result_is_hidden) { boost::shared_ptr the_copy; char buf[32]; @@ -1286,7 +1253,7 @@ Playlist::cut (samplepos_t start, samplecnt_t cnt, bool result_is_hidden) } boost::shared_ptr -Playlist::copy (samplepos_t start, samplecnt_t cnt, bool result_is_hidden) +Playlist::copy (timepos_t const & start, timecnt_t const & cnt, bool result_is_hidden) { char buf[32]; @@ -1301,36 +1268,25 @@ Playlist::copy (samplepos_t start, samplecnt_t cnt, bool result_is_hidden) } int -Playlist::paste (boost::shared_ptr other, samplepos_t position, float times, const int32_t sub_num) +Playlist::paste (boost::shared_ptr other, timepos_t const & position, float times) { times = fabs (times); { RegionReadLock rl2 (other.get ()); - int itimes = (int)floor (times); - samplepos_t pos = position; - samplecnt_t const shift = other->_get_extent ().second; - layer_t top = top_layer (); + int itimes = (int) floor (times); + timepos_t pos = position; + timecnt_t const shift (other->_get_extent().second, other->_get_extent().first); + layer_t top = top_layer (); + + { { RegionWriteLock rl1 (this); while (itimes--) { -<<<<<<< HEAD for (RegionList::iterator i = other->regions.begin (); i != other->regions.end (); ++i) { boost::shared_ptr copy_of_region = RegionFactory::create (*i, true, false, &rl1.thawlist); -======= -<<<<<<< HEAD -<<<<<<< HEAD - for (RegionList::iterator i = other->regions.begin (); i != other->regions.end (); ++i) { - boost::shared_ptr copy_of_region = RegionFactory::create (*i, true, false, &rl1.thawlist); -======= -======= ->>>>>>> Revert "NO-OP: code formatting and cleanup, thanks clang-format" - for (RegionList::iterator i = other->regions.begin(); i != other->regions.end(); ++i) { - boost::shared_ptr copy_of_region = RegionFactory::create (*i, true); ->>>>>>> Revert "NO-OP: code formatting and cleanup, thanks clang-format" ->>>>>>> 0bbe6796b9 (Revert "NO-OP: code formatting and cleanup, thanks clang-format") /* put these new regions on top of all existing ones, but preserve the ordering they had in the original playlist. @@ -1343,19 +1299,18 @@ Playlist::paste (boost::shared_ptr other, samplepos_t position, float } } } - return 0; } void -Playlist::duplicate (boost::shared_ptr region, samplepos_t position, float times) +Playlist::duplicate (boost::shared_ptr region, timepos_t & position, float times) { - duplicate (region, position, region->length (), times); + duplicate(region, position, region->nt_length(), times); } /** @param gap from the beginning of the region to the next beginning */ void -Playlist::duplicate (boost::shared_ptr region, samplepos_t position, samplecnt_t gap, float times) +Playlist::duplicate (boost::shared_ptr region, timepos_t & position, timecnt_t const & gap, float times) { times = fabs (times); @@ -1370,14 +1325,14 @@ Playlist::duplicate (boost::shared_ptr region, samplepos_t position, sam } if (floor (times) != times) { - samplecnt_t length = (samplecnt_t)floor (region->length () * (times - floor (times))); - string name; - RegionFactory::region_name (name, region->name (), false); + timecnt_t length = region->nt_length() * (times - floor (times)); + string name; + RegionFactory::region_name (name, region->name(), false); { PropertyList plist; - plist.add (Properties::start, region->start ()); + plist.add (Properties::start, region->nt_start()); plist.add (Properties::length, length); plist.add (Properties::name, name); @@ -1391,146 +1346,91 @@ Playlist::duplicate (boost::shared_ptr region, samplepos_t position, sam /** @param gap from the beginning of the region to the next beginning */ /** @param end the first sample that does _not_ contain a duplicated sample */ void -Playlist::duplicate_until (boost::shared_ptr region, samplepos_t position, samplecnt_t gap, samplepos_t end) +Playlist::duplicate_until (boost::shared_ptr region, timepos_t & position, timecnt_t const & gap, timepos_t const & end) { RegionWriteLock rl (this); -<<<<<<< HEAD -======= -<<<<<<< HEAD -<<<<<<< HEAD ->>>>>>> 0bbe6796b9 (Revert "NO-OP: code formatting and cleanup, thanks clang-format") - while (position + region->length () - 1 < end) { - boost::shared_ptr copy = RegionFactory::create (region, true, false, &rl.thawlist); - add_region_internal (copy, position, rl.thawlist); - set_layer (copy, DBL_MAX); - position += gap; - } -<<<<<<< HEAD -======= -======= -======= ->>>>>>> Revert "NO-OP: code formatting and cleanup, thanks clang-format" - while (position + region->length() - 1 < end) { - boost::shared_ptr copy = RegionFactory::create (region, true); + RegionWriteLock rl (this); + + while (position + region->length().decrement() < end) { + boost::shared_ptr copy = RegionFactory::create (region, true, false, &rl.thawlist); add_region_internal (copy, position, rl.thawlist); set_layer (copy, DBL_MAX); position += gap; } -<<<<<<< HEAD ->>>>>>> Revert "NO-OP: code formatting and cleanup, thanks clang-format" -======= ->>>>>>> Revert "NO-OP: code formatting and cleanup, thanks clang-format" ->>>>>>> 0bbe6796b9 (Revert "NO-OP: code formatting and cleanup, thanks clang-format") + if (position < end) { + timecnt_t length = min (region->length(), position.distance (end)); + string name; + RegionFactory::region_name (name, region->name(), false); - if (position < end) { - samplecnt_t length = min (region->length (), end - position); - string name; - RegionFactory::region_name (name, region->name (), false); + { + PropertyList plist; - { - PropertyList plist; + plist.add (Properties::start, region->start()); + plist.add (Properties::length, length); + plist.add (Properties::name, name); - plist.add (Properties::start, region->start ()); - plist.add (Properties::length, length); - plist.add (Properties::name, name); - -<<<<<<< HEAD -======= -<<<<<<< HEAD -<<<<<<< HEAD ->>>>>>> 0bbe6796b9 (Revert "NO-OP: code formatting and cleanup, thanks clang-format") boost::shared_ptr sub = RegionFactory::create (region, plist, false, &rl.thawlist); add_region_internal (sub, position, rl.thawlist); set_layer (sub, DBL_MAX); } } -<<<<<<< HEAD -======= -======= -======= ->>>>>>> Revert "NO-OP: code formatting and cleanup, thanks clang-format" - boost::shared_ptr sub = RegionFactory::create (region, plist); - add_region_internal (sub, position, rl.thawlist); - set_layer (sub, DBL_MAX); - } - } -<<<<<<< HEAD ->>>>>>> Revert "NO-OP: code formatting and cleanup, thanks clang-format" -======= ->>>>>>> Revert "NO-OP: code formatting and cleanup, thanks clang-format" ->>>>>>> 0bbe6796b9 (Revert "NO-OP: code formatting and cleanup, thanks clang-format") } void -Playlist::duplicate_range (AudioRange& range, float times) +Playlist::duplicate_range (TimelineRange& range, float times) { - boost::shared_ptr pl = copy (range.start, range.length (), true); - samplecnt_t offset = range.end - range.start; - paste (pl, range.start + offset, times, 0); + boost::shared_ptr pl = copy (range.start(), range.length(), true); + paste (pl, range.end(), times); } void -Playlist::duplicate_ranges (std::list& ranges, float times) +Playlist::duplicate_ranges (std::list& ranges, float times) { if (ranges.empty ()) { return; } - samplepos_t min_pos = max_samplepos; - samplepos_t max_pos = 0; + timepos_t min_pos = std::numeric_limits::max(); + timepos_t max_pos = std::numeric_limits::min(); - for (std::list::const_iterator i = ranges.begin (); - i != ranges.end (); + for (std::list::const_iterator i = ranges.begin(); + i != ranges.end(); ++i) { - min_pos = min (min_pos, (*i).start); - max_pos = max (max_pos, (*i).end); + min_pos = min (min_pos, (*i).start()); + max_pos = max (max_pos, (*i).end()); } - samplecnt_t offset = max_pos - min_pos; + timecnt_t offset = min_pos.distance (max_pos); int count = 1; int itimes = (int)floor (times); while (itimes--) { - for (list::iterator i = ranges.begin (); i != ranges.end (); ++i) { - boost::shared_ptr pl = copy ((*i).start, (*i).length (), true); - paste (pl, (*i).start + (offset * count), 1.0f, 0); + for (list::iterator i = ranges.begin (); i != ranges.end (); ++i) { + boost::shared_ptr pl = copy ((*i).start(), (*i).length (), true); + paste (pl, (*i).start() + (offset * count), 1.0f); } ++count; } } void -Playlist::shift (samplepos_t at, sampleoffset_t distance, bool move_intersected, bool ignore_music_glue) +Playlist::shift (timepos_t const & at, timecnt_t const & distance, bool move_intersected, bool ignore_music_glue) { PBD::Unwinder uw (_playlist_shift_active, true); -<<<<<<< HEAD - RegionWriteLock rlock (this); - RegionList copy (regions.rlist ()); - RegionList fixup; - - for (RegionList::iterator r = copy.begin (); r != copy.end (); ++r) { - if ((*r)->last_sample () < at) { -======= + PBD::Unwinder uw (_playlist_shift_active, true); RegionWriteLock rlock (this); RegionList copy (regions.rlist()); RegionList fixup; -<<<<<<< HEAD for (RegionList::iterator r = copy.begin(); r != copy.end(); ++r) { -======= - - for (RegionList::iterator r = copy.begin(); r != copy.end(); ++r) { - ->>>>>>> Revert "NO-OP: code formatting and cleanup, thanks clang-format" - if ((*r)->last_sample() < at) { ->>>>>>> 0bbe6796b9 (Revert "NO-OP: code formatting and cleanup, thanks clang-format") + if ((*r)->nt_last() < at) { /* too early */ continue; } - if (at > (*r)->first_sample () && at < (*r)->last_sample ()) { + if (at > (*r)->position() && at < (*r)->nt_last()) { /* intersected region */ if (!move_intersected) { continue; @@ -1541,23 +1441,23 @@ Playlist::shift (samplepos_t at, sampleoffset_t distance, bool move_intersected, * has to be done separately. */ - if (!ignore_music_glue && (*r)->position_lock_style () != AudioTime) { + if (!ignore_music_glue && (*r)->position().time_domain() != Temporal::AudioTime) { fixup.push_back (*r); continue; } rlock.thawlist.add (*r); - (*r)->set_position ((*r)->position () + distance); + (*r)->set_position ((*r)->position() + distance); } /* XXX: may not be necessary; Region::post_set should do this, I think */ - for (RegionList::iterator r = fixup.begin (); r != fixup.end (); ++r) { - (*r)->recompute_position_from_lock_style (0); + for (RegionList::iterator r = fixup.begin(); r != fixup.end(); ++r) { + (*r)->recompute_position_from_time_domain (); } } void -Playlist::split (const MusicSample& at) +Playlist::split (timepos_t const & at) { RegionWriteLock rlock (this); RegionList copy (regions.rlist ()); @@ -1570,38 +1470,38 @@ Playlist::split (const MusicSample& at) } void -Playlist::split_region (boost::shared_ptr region, const MusicSample& playlist_position) +Playlist::split_region (boost::shared_ptr region, timepos_t const & playlist_position) { RegionWriteLock rl (this); _split_region (region, playlist_position, rl.thawlist); } void -Playlist::_split_region (boost::shared_ptr region, const MusicSample& playlist_position, ThawList& thawlist) +Playlist::_split_region (boost::shared_ptr region, timepos_t const & playlist_position, Thawlist& thawlist) { - if (!region->covers (playlist_position.sample)) { + if (!region->covers (playlist_position)) { return; } - if (region->position () == playlist_position.sample || - region->last_sample () == playlist_position.sample) { + if (region->nt_position() == playlist_position || + region->nt_last() == playlist_position) { return; } boost::shared_ptr left; boost::shared_ptr right; - MusicSample before (playlist_position.sample - region->position (), playlist_position.division); - MusicSample after (region->length () - before.sample, 0); - string before_name; - string after_name; + timecnt_t before (region->nt_position().distance (playlist_position)); + timecnt_t after (region->nt_length() - before); + string before_name; + string after_name; RegionFactory::region_name (before_name, region->name (), false); { PropertyList plist; - plist.add (Properties::length, before.sample); + plist.add (Properties::length, before); plist.add (Properties::name, before_name); plist.add (Properties::left_of_split, true); plist.add (Properties::layering_index, region->layering_index ()); @@ -1611,7 +1511,7 @@ Playlist::_split_region (boost::shared_ptr region, const MusicSample& pl * since it supplies that offset to the Region constructor, which * is necessary to get audio region gain envelopes right. */ - left = RegionFactory::create (region, MusicSample (0, 0), plist, true, &thawlist); + left = RegionFactory::create (region, timecnt_t (before.time_domain()), plist, true, &thawlist); } RegionFactory::region_name (after_name, region->name (), false); @@ -1619,7 +1519,7 @@ Playlist::_split_region (boost::shared_ptr region, const MusicSample& pl { PropertyList plist; - plist.add (Properties::length, after.sample); + plist.add (Properties::length, after); plist.add (Properties::name, after_name); plist.add (Properties::right_of_split, true); plist.add (Properties::layering_index, region->layering_index ()); @@ -1629,8 +1529,8 @@ Playlist::_split_region (boost::shared_ptr region, const MusicSample& pl right = RegionFactory::create (region, before, plist, true, &thawlist); } - add_region_internal (left, region->position (), thawlist, 0); - add_region_internal (right, region->position () + before.sample, thawlist, before.division); + add_region_internal (left, region->nt_position(), thawlist); + add_region_internal (right, region->nt_position() + before, thawlist); remove_region_internal (region, thawlist); } @@ -1662,30 +1562,13 @@ Playlist::SoloSelectedActive () } void -Playlist::ripple (samplepos_t at, samplecnt_t distance, RegionList* exclude) -{ - ripple_locked (at, distance, exclude); -} void -Playlist::ripple_locked (samplepos_t at, samplecnt_t distance, RegionList* exclude) +Playlist::ripple_locked (timepos_t const & at, timecnt_t const & distance, RegionList *exclude, ThawList& thawlist) + { bool changed = false; - { - RegionWriteLock rl (this); - changed = ripple_unlocked (at, distance, exclude, rl.thawlist); - } - if (changed) { - notify_contents_changed (); - } -} - - -bool -Playlist::ripple_unlocked (samplepos_t at, samplecnt_t distance, RegionList* exclude, ThawList& thawlist) -{ - bool changed = false; if (distance == 0 || regions.empty()) { return false; @@ -1702,9 +1585,9 @@ Playlist::ripple_unlocked (samplepos_t at, samplecnt_t distance, RegionList* exc } } - if ((*i)->position () >= at) { - samplepos_t new_pos = (*i)->position () + distance; - samplepos_t limit = max_samplepos - (*i)->length (); + if ((*i)->nt_position() >= at) { + timepos_t new_pos = (*i)->nt_position() + distance; + timepos_t limit = std::numeric_limits::max().earlier ((*i)->nt_length()); if (new_pos < 0) { new_pos = 0; } else if (new_pos >= limit) { @@ -1751,14 +1634,15 @@ Playlist::region_bounds_changed (const PropertyChange& what_changed, boost::shar } if (what_changed.contains (Properties::position) || what_changed.contains (Properties::length)) { - sampleoffset_t delta = 0; + + timecnt_t delta; if (what_changed.contains (Properties::position)) { - delta = region->position () - region->last_position (); + delta = region->last_position().distance (region->nt_position()); } if (what_changed.contains (Properties::length)) { - delta += region->length () - region->last_length (); + delta += region->nt_length() - region->last_length(); } if (holding_state ()) { @@ -1766,9 +1650,9 @@ Playlist::region_bounds_changed (const PropertyChange& what_changed, boost::shar } else { notify_contents_changed (); relayer (); - list > xf; - xf.push_back (Evoral::Range (region->last_range ())); - xf.push_back (Evoral::Range (region->range ())); + list xf; + xf.push_back (Temporal::Range (region->last_range())); + xf.push_back (Temporal::Range (region->range())); coalesce_and_check_crossfades (xf); } } @@ -1919,20 +1803,20 @@ Playlist::deep_sources (std::set >& sources) const } boost::shared_ptr -Playlist::regions_at (samplepos_t sample) +Playlist::regions_at (timepos_t const & pos) { RegionReadLock rlock (this); - return find_regions_at (sample); + return find_regions_at (pos); } uint32_t -Playlist::count_regions_at (samplepos_t sample) const +Playlist::count_regions_at (timepos_t const & pos) const { RegionReadLock rlock (const_cast (this)); uint32_t cnt = 0; - for (RegionList::const_iterator i = regions.begin (); i != regions.end (); ++i) { - if ((*i)->covers (sample)) { + for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) { + if ((*i)->covers (pos)) { cnt++; } } @@ -1941,11 +1825,11 @@ Playlist::count_regions_at (samplepos_t sample) const } boost::shared_ptr -Playlist::top_region_at (samplepos_t sample) +Playlist::top_region_at (timepos_t const & pos) { - RegionReadLock rlock (this); - boost::shared_ptr rlist = find_regions_at (sample); - boost::shared_ptr region; + RegionReadLock rlock (this); + boost::shared_ptr rlist = find_regions_at (pos); + boost::shared_ptr region; if (rlist->size ()) { RegionSortByLayer cmp; @@ -1957,10 +1841,10 @@ Playlist::top_region_at (samplepos_t sample) } boost::shared_ptr -Playlist::top_unmuted_region_at (samplepos_t sample) +Playlist::top_unmuted_region_at (timepos_t const & pos) { - RegionReadLock rlock (this); - boost::shared_ptr rlist = find_regions_at (sample); + RegionReadLock rlock (this); + boost::shared_ptr rlist = find_regions_at (pos); for (RegionList::iterator i = rlist->begin (); i != rlist->end ();) { RegionList::iterator tmp = i; @@ -1986,14 +1870,14 @@ Playlist::top_unmuted_region_at (samplepos_t sample) } boost::shared_ptr -Playlist::find_regions_at (samplepos_t sample) +Playlist::find_regions_at (timepos_t const & pos) { /* Caller must hold lock */ boost::shared_ptr rlist (new RegionList); - for (RegionList::iterator i = regions.begin (); i != regions.end (); ++i) { - if ((*i)->covers (sample)) { + for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) { + if ((*i)->covers (pos)) { rlist->push_back (*i); } } @@ -2002,13 +1886,13 @@ Playlist::find_regions_at (samplepos_t sample) } boost::shared_ptr -Playlist::regions_with_start_within (Evoral::Range range) +Playlist::regions_with_start_within (Temporal::Range range) { RegionReadLock rlock (this); boost::shared_ptr rlist (new RegionList); - for (RegionList::iterator i = regions.begin (); i != regions.end (); ++i) { - if ((*i)->first_sample () >= range.from && (*i)->first_sample () <= range.to) { + for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) { + if ((*i)->nt_position() >= range.start() && (*i)->nt_position() < range.end()) { rlist->push_back (*i); } } @@ -2017,13 +1901,13 @@ Playlist::regions_with_start_within (Evoral::Range range) } boost::shared_ptr -Playlist::regions_with_end_within (Evoral::Range range) +Playlist::regions_with_end_within (Temporal::Range range) { RegionReadLock rlock (this); boost::shared_ptr rlist (new RegionList); - for (RegionList::iterator i = regions.begin (); i != regions.end (); ++i) { - if ((*i)->last_sample () >= range.from && (*i)->last_sample () <= range.to) { + for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) { + if ((*i)->nt_last() >= range.start() && (*i)->nt_last() < range.end()) { rlist->push_back (*i); } } @@ -2032,19 +1916,19 @@ Playlist::regions_with_end_within (Evoral::Range range) } boost::shared_ptr -Playlist::regions_touched (samplepos_t start, samplepos_t end) +Playlist::regions_touched (timepos_t const & start, timepos_t const & end) { RegionReadLock rlock (this); return regions_touched_locked (start, end); } boost::shared_ptr -Playlist::regions_touched_locked (samplepos_t start, samplepos_t end) +Playlist::regions_touched_locked (timepos_t const & start, timepos_t const & end) { boost::shared_ptr rlist (new RegionList); - for (RegionList::iterator i = regions.begin (); i != regions.end (); ++i) { - if ((*i)->coverage (start, end) != Evoral::OverlapNone) { + for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) { + if ((*i)->coverage (start, end) != Temporal::OverlapNone) { rlist->push_back (*i); } } @@ -2053,7 +1937,7 @@ Playlist::regions_touched_locked (samplepos_t start, samplepos_t end) } samplepos_t -Playlist::find_next_transient (samplepos_t from, int dir) +Playlist::find_next_transient (timepos_t const & from, int dir) { RegionReadLock rlock (this); AnalysisFeatureList points; @@ -2061,20 +1945,18 @@ Playlist::find_next_transient (samplepos_t from, int dir) for (RegionList::iterator i = regions.begin (); i != regions.end (); ++i) { if (dir > 0) { - if ((*i)->last_sample () < from) { + if ((*i)->nt_last() < from) { continue; } } else { - if ((*i)->first_sample () > from) { + if ((*i)->nt_position() > from) { continue; } } (*i)->get_transients (these_points); - /* add first sample, just, err, because */ - - these_points.push_back ((*i)->first_sample ()); + these_points.push_back ((*i)->position_sample()); points.insert (points.end (), these_points.begin (), these_points.end ()); these_points.clear (); @@ -2088,22 +1970,22 @@ Playlist::find_next_transient (samplepos_t from, int dir) bool reached = false; if (dir > 0) { - for (AnalysisFeatureList::const_iterator x = points.begin (); x != points.end (); ++x) { - if ((*x) >= from) { + for (AnalysisFeatureList::const_iterator x = points.begin(); x != points.end(); ++x) { + if ((*x) >= from.samples()) { reached = true; } - if (reached && (*x) > from) { + if (reached && (*x) > from.samples()) { return *x; } } } else { - for (AnalysisFeatureList::reverse_iterator x = points.rbegin (); x != points.rend (); ++x) { - if ((*x) <= from) { + for (AnalysisFeatureList::reverse_iterator x = points.rbegin(); x != points.rend(); ++x) { + if ((*x) <= from.samples()) { reached = true; } - if (reached && (*x) < from) { + if (reached && (*x) < from.samples()) { return *x; } } @@ -2113,75 +1995,59 @@ Playlist::find_next_transient (samplepos_t from, int dir) } boost::shared_ptr -Playlist::find_next_region (samplepos_t sample, RegionPoint point, int dir) +Playlist::find_next_region (timepos_t const & pos, RegionPoint point, int dir) { RegionReadLock rlock (this); boost::shared_ptr ret; - samplepos_t closest = max_samplepos; + timecnt_t closest = std::numeric_limits::max(); bool end_iter = false; -<<<<<<< HEAD - for (RegionList::iterator i = regions.begin (); i != regions.end (); ++i) { - if (end_iter) - break; - - sampleoffset_t distance; - boost::shared_ptr r = (*i); - samplepos_t pos = 0; -======= for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) { -<<<<<<< HEAD if(end_iter) break; -======= - - if(end_iter) break; - ->>>>>>> Revert "NO-OP: code formatting and cleanup, thanks clang-format" - sampleoffset_t distance; + timecnt_t distance; boost::shared_ptr r = (*i); - samplepos_t pos = 0; ->>>>>>> 0bbe6796b9 (Revert "NO-OP: code formatting and cleanup, thanks clang-format") + timepos_t rpos; switch (point) { - case Start: - pos = r->first_sample (); - break; - case End: - pos = r->last_sample (); - break; - case SyncPoint: - pos = r->sync_position (); - break; + case Start: + rpos = r->position (); + break; + case End: + rpos = r->nt_last (); + break; + case SyncPoint: + rpos = r->sync_position (); + break; } switch (dir) { - case 1: /* forwards */ + case 1: /* forwards */ - if (pos > sample) { - if ((distance = pos - sample) < closest) { - closest = distance; - ret = r; - end_iter = true; - } - } - - break; - - default: /* backwards */ - - if (pos < sample) { - if ((distance = sample - pos) < closest) { - closest = distance; - ret = r; - } - } else { + if (rpos > pos) { + if ((distance = rpos.distance (pos)) < closest) { + closest = distance; + ret = r; end_iter = true; } + } - break; + break; + + default: /* backwards */ + + if (rpos < pos) { + if ((distance = rpos.distance (pos)) < closest) { + closest = distance; + ret = r; + } + } else { + end_iter = true; + } + + break; } } @@ -2219,35 +2085,35 @@ Playlist::find_prev_region_start (samplepos_t sample) return ret; } -samplepos_t -Playlist::find_next_region_boundary (samplepos_t sample, int dir) +timepos_t +Playlist::find_next_region_boundary (timepos_t const & pos, int dir) { RegionReadLock rlock (this); - samplepos_t closest = max_samplepos; - samplepos_t ret = -1; + timecnt_t closest = std::numeric_limits::max(); + timepos_t ret; if (dir > 0) { for (RegionList::iterator i = regions.begin (); i != regions.end (); ++i) { boost::shared_ptr r = (*i); - sampleoffset_t distance; - const samplepos_t first_sample = r->first_sample (); - const samplepos_t last_sample = r->last_sample (); + timecnt_t distance; - if (first_sample > sample) { - distance = first_sample - sample; + if (r->nt_position() > pos) { + + distance = pos.distance (r->nt_position()); if (distance < closest) { - ret = first_sample; + ret = r->nt_position (); closest = distance; } } - if (last_sample > sample) { - distance = last_sample - sample; + if (r->nt_last() > pos) { + + distance = pos.distance (r->nt_last()); if (distance < closest) { - ret = last_sample; + ret = r->nt_last(); closest = distance; } } @@ -2256,24 +2122,24 @@ Playlist::find_next_region_boundary (samplepos_t sample, int dir) } else { for (RegionList::reverse_iterator i = regions.rbegin (); i != regions.rend (); ++i) { boost::shared_ptr r = (*i); - sampleoffset_t distance; - const samplepos_t first_sample = r->first_sample (); - const samplepos_t last_sample = r->last_sample (); + timecnt_t distance; - if (last_sample < sample) { - distance = sample - last_sample; + if (r->nt_last() < pos) { + + distance = r->nt_last().distance (pos); if (distance < closest) { - ret = last_sample; + ret = r->nt_last(); closest = distance; } } - if (first_sample < sample) { - distance = sample - first_sample; + if (r->nt_position() < pos) { + + distance = r->nt_position().distance (pos); if (distance < closest) { - ret = first_sample; + ret = r->nt_position(); closest = distance; } } @@ -2330,8 +2196,8 @@ Playlist::update (const RegionListProperty::ChangeRecord& change) RegionWriteLock rlock (this); freeze_locked (); /* add the added regions */ - for (RegionListProperty::ChangeContainer::const_iterator i = change.added.begin (); i != change.added.end (); ++i) { - add_region_internal ((*i), (*i)->position (), rlock.thawlist); + for (RegionListProperty::ChangeContainer::const_iterator i = change.added.begin(); i != change.added.end(); ++i) { + add_region_internal ((*i), (*i)->nt_position(), rlock.thawlist); } /* remove the removed regions */ for (RegionListProperty::ChangeContainer::const_iterator i = change.removed.begin (); i != change.removed.end (); ++i) { @@ -2426,7 +2292,7 @@ Playlist::set_state (const XMLNode& node, int version) { RegionWriteLock rlock (this); - add_region_internal (region, region->position (), rlock.thawlist); + add_region_internal (region, region->nt_position(), rlock.thawlist); } region->resume_property_changes (); @@ -2525,7 +2391,7 @@ Playlist::all_regions_empty () const return all_regions.empty (); } -pair +pair Playlist::get_extent () const { if (_cached_extent) { @@ -2537,26 +2403,26 @@ Playlist::get_extent () const return _cached_extent.value (); } -pair +pair Playlist::get_extent_with_endspace () const { - pair l = get_extent (); + pair l = get_extent(); l.second += _end_space; return l; } -pair +pair Playlist::_get_extent () const { - pair ext (max_samplepos, 0); + pair ext (std::numeric_limits::max(), std::numeric_limits::min()); if (regions.empty ()) { ext.first = 0; return ext; } - for (RegionList::const_iterator i = regions.begin (); i != regions.end (); ++i) { - pair const e ((*i)->position (), (*i)->position () + (*i)->length ()); + for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) { + pair const e ((*i)->nt_position(), (*i)->nt_position() + (*i)->nt_length()); if (e.first < ext.first) { ext.first = e.first; } @@ -2639,9 +2505,8 @@ Playlist::setup_layering_indices (RegionList const& regions) } struct LaterHigherSort { - bool operator() (boost::shared_ptr a, boost::shared_ptr b) - { - return a->position () < b->position (); + bool operator () (boost::shared_ptr a, boost::shared_ptr b) { + return a->nt_position() < b->nt_position(); } }; @@ -2666,15 +2531,16 @@ Playlist::relayer () int const divisions = 512; /* find the start and end positions of the regions on this playlist */ - samplepos_t start = INT64_MAX; - samplepos_t end = 0; - for (RegionList::const_iterator i = regions.begin (); i != regions.end (); ++i) { - start = min (start, (*i)->position ()); - end = max (end, (*i)->position () + (*i)->length ()); + timepos_t start = std::numeric_limits::max(); + timepos_t end = std::numeric_limits::min(); + + for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) { + start = min (start, (*i)->nt_position()); + end = max (end, (*i)->nt_position() + (*i)->nt_length()); } /* hence the size of each time division */ - double const division_size = (end - start) / double(divisions); + double const division_size = (end.samples() - start.samples()) / double (divisions); vector > layers; layers.push_back (vector (divisions)); @@ -2704,8 +2570,8 @@ Playlist::relayer () int end_division = 0; if (division_size > 0) { - start_division = floor (((*i)->position () - start) / division_size); - end_division = floor (((*i)->position () + (*i)->length () - start) / division_size); + start_division = floor ( ((*i)->position_sample() - start.samples()) / division_size); + end_division = floor ( ((*i)->position_sample() + (*i)->length_samples() - start.samples()) / division_size ); if (end_division == divisions) { end_division--; } @@ -2801,7 +2667,7 @@ Playlist::lower_region_to_bottom (boost::shared_ptr region) } void -Playlist::nudge_after (samplepos_t start, samplecnt_t distance, bool forwards) +Playlist::nudge_after (timepos_t const & start, timecnt_t const & distance, bool forwards) { RegionList::iterator i; bool moved = false; @@ -2809,22 +2675,26 @@ Playlist::nudge_after (samplepos_t start, samplecnt_t distance, bool forwards) _nudging = true; { - RegionWriteLock rlock (const_cast (this)); + RegionWriteLock rlock (const_cast (this)); - for (i = regions.begin (); i != regions.end (); ++i) { - if ((*i)->position () >= start) { - samplepos_t new_pos; + for (i = regions.begin(); i != regions.end(); ++i) { + + if ((*i)->nt_position() >= start) { + + timepos_t new_pos; if (forwards) { - if ((*i)->last_sample () > max_samplepos - distance) { - new_pos = max_samplepos - (*i)->length (); + + if ((*i)->nt_last() > std::numeric_limits::max().earlier (distance)) { + new_pos = std::numeric_limits::max().earlier ((*i)->nt_length()); } else { - new_pos = (*i)->position () + distance; + new_pos = (*i)->nt_position() + distance; } } else { - if ((*i)->position () > distance) { - new_pos = (*i)->position () - distance; + + if ((*i)->nt_position() > distance) { + new_pos = (*i)->nt_position().earlier (distance); } else { new_pos = 0; } @@ -2942,10 +2812,10 @@ Playlist::dump () const for (RegionList::const_iterator i = regions.begin (); i != regions.end (); ++i) { r = *i; - cerr << " " << r->name () << " [" - << r->start () << "+" << r->length () + cerr << " " << r->name() << " [" + << r->nt_start() << "+" << r->nt_length() << "] at " - << r->position () + << r->nt_position() << " on layer " << r->layer () << endl; @@ -2985,26 +2855,26 @@ Playlist::shuffle (boost::shared_ptr region, int dir) break; } - samplepos_t new_pos; + timepos_t new_pos; - if ((*next)->position () != region->last_sample () + 1) { + if ((*next)->nt_position() != region->last_sample() + 1) { /* they didn't used to touch, so after shuffle, * just have them swap positions. */ - new_pos = (*next)->position (); + new_pos = (*next)->nt_position(); } else { /* they used to touch, so after shuffle, * make sure they still do. put the earlier * region where the later one will end after * it is moved. */ - new_pos = region->position () + (*next)->length (); + new_pos = region->nt_position() + (*next)->nt_length(); } rlock.thawlist.add (*next); rlock.thawlist.add (region); - (*next)->set_position (region->position ()); + (*next)->set_position (region->nt_position()); region->set_position (new_pos); /* avoid a full sort */ @@ -3028,24 +2898,24 @@ Playlist::shuffle (boost::shared_ptr region, int dir) break; } - samplepos_t new_pos; - if (region->position () != (*prev)->last_sample () + 1) { + timepos_t new_pos; + if (region->nt_position() != (*prev)->last_sample() + 1) { /* they didn't used to touch, so after shuffle, * just have them swap positions. */ - new_pos = region->position (); + new_pos = region->nt_position(); } else { /* they used to touch, so after shuffle, * make sure they still do. put the earlier * one where the later one will end after */ - new_pos = (*prev)->position () + region->length (); + new_pos = (*prev)->nt_position() + region->nt_length(); } rlock.thawlist.add (region); rlock.thawlist.add (*prev); - region->set_position ((*prev)->position ()); + region->set_position ((*prev)->nt_position()); (*prev)->set_position (new_pos); /* avoid a full sort */ @@ -3082,6 +2952,12 @@ Playlist::region_is_shuffle_constrained (boost::shared_ptr) return false; } +void +Playlist::ripple (timepos_t const & at, timecnt_t const & distance, RegionList *exclude) +{ + ripple_locked (at, distance, exclude); +} + void Playlist::update_after_tempo_map_change () { @@ -3110,7 +2986,7 @@ Playlist::foreach_region (boost::function)> s) } bool -Playlist::has_region_at (samplepos_t const p) const +Playlist::has_region_at (timepos_t const & p) const { RegionReadLock (const_cast (this)); @@ -3127,8 +3003,8 @@ Playlist::has_region_at (samplepos_t const p) const * @param t Time to look from. * @return Position of next top-layered region, or max_samplepos if there isn't one. */ -samplepos_t -Playlist::find_next_top_layer_position (samplepos_t t) const +timepos_t +Playlist::find_next_top_layer_position (timepos_t const & t) const { RegionReadLock rlock (const_cast (this)); @@ -3137,63 +3013,44 @@ Playlist::find_next_top_layer_position (samplepos_t t) const RegionList copy = regions.rlist (); copy.sort (RegionSortByPosition ()); - for (RegionList::const_iterator i = copy.begin (); i != copy.end (); ++i) { - if ((*i)->position () >= t && (*i)->layer () == top) { - return (*i)->position (); + for (RegionList::const_iterator i = copy.begin(); i != copy.end(); ++i) { + if ((*i)->nt_position() >= t && (*i)->layer() == top) { + return (*i)->nt_position(); } } - return max_samplepos; + return std::numeric_limits::max(); } boost::shared_ptr Playlist::combine (const RegionList& r) { -<<<<<<< HEAD -======= -<<<<<<< HEAD -<<<<<<< HEAD ->>>>>>> 0bbe6796b9 (Revert "NO-OP: code formatting and cleanup, thanks clang-format") + ThawList thawlist; PropertyList plist; - uint32_t channels = 0; + SourceList::size_type channels = 0; uint32_t layer = 0; - samplepos_t earliest_position = max_samplepos; + timepos_t earliest_position = std::numeric_limits::max(); vector old_and_new_regions; -<<<<<<< HEAD -======= -======= -======= ->>>>>>> Revert "NO-OP: code formatting and cleanup, thanks clang-format" - PropertyList plist; - uint32_t channels = 0; - uint32_t layer = 0; - samplepos_t earliest_position = max_samplepos; - vector old_and_new_regions; -<<<<<<< HEAD ->>>>>>> Revert "NO-OP: code formatting and cleanup, thanks clang-format" -======= ->>>>>>> Revert "NO-OP: code formatting and cleanup, thanks clang-format" ->>>>>>> 0bbe6796b9 (Revert "NO-OP: code formatting and cleanup, thanks clang-format") vector > originals; vector > copies; - string parent_name; - string child_name; - uint32_t max_level = 0; + string parent_name; + string child_name; + uint32_t max_level = 0; /* find the maximum depth of all the regions we're combining */ - for (RegionList::const_iterator i = r.begin (); i != r.end (); ++i) { - max_level = max (max_level, (*i)->max_source_level ()); + for (RegionList::const_iterator i = r.begin(); i != r.end(); ++i) { + max_level = max (max_level, (*i)->max_source_level()); } - parent_name = RegionFactory::compound_region_name (name (), combine_ops (), max_level, true); - child_name = RegionFactory::compound_region_name (name (), combine_ops (), max_level, false); + parent_name = RegionFactory::compound_region_name (name(), combine_ops(), max_level, true); + child_name = RegionFactory::compound_region_name (name(), combine_ops(), max_level, false); boost::shared_ptr pl = PlaylistFactory::create (_type, _session, parent_name, true); - for (RegionList::const_iterator i = r.begin (); i != r.end (); ++i) { - earliest_position = min (earliest_position, (*i)->position ()); + for (RegionList::const_iterator i = r.begin(); i != r.end(); ++i) { + earliest_position = min (earliest_position, (*i)->position()); } /* enable this so that we do not try to create xfades etc. as we add @@ -3206,43 +3063,33 @@ Playlist::combine (const RegionList& r) * route_time_axis passes 'selected_regions' - which is not sorted. * here we need the top-most first, then every layer's region sorted by position. */ - RegionList sorted (r); - sorted.sort (RegionSortByLayerAndPosition ()); + RegionList sorted(r); + sorted.sort(RegionSortByLayerAndPosition()); + + for (RegionList::const_iterator i = sorted.begin(); i != sorted.end(); ++i) { - for (RegionList::const_iterator i = sorted.begin (); i != sorted.end (); ++i) { /* copy the region */ boost::shared_ptr original_region = (*i); -<<<<<<< HEAD boost::shared_ptr copied_region = RegionFactory::create (original_region, false, false, &thawlist); -======= -<<<<<<< HEAD -<<<<<<< HEAD - boost::shared_ptr copied_region = RegionFactory::create (original_region, false, false, &thawlist); -======= - boost::shared_ptr copied_region = RegionFactory::create (original_region, false); ->>>>>>> Revert "NO-OP: code formatting and cleanup, thanks clang-format" -======= - boost::shared_ptr copied_region = RegionFactory::create (original_region, false); ->>>>>>> Revert "NO-OP: code formatting and cleanup, thanks clang-format" ->>>>>>> 0bbe6796b9 (Revert "NO-OP: code formatting and cleanup, thanks clang-format") - old_and_new_regions.push_back (TwoRegions (original_region, copied_region)); + old_and_new_regions.push_back (TwoRegions (original_region,copied_region)); originals.push_back (original_region); copies.push_back (copied_region); RegionFactory::add_compound_association (original_region, copied_region); /* make position relative to zero */ - pl->add_region_internal (copied_region, original_region->position () - earliest_position, thawlist); + + pl->add_region_internal (copied_region, original_region->position().earlier (timecnt_t (earliest_position, earliest_position)), thawlist); /* use the maximum number of channels for any region */ - channels = max (channels, original_region->n_channels ()); + channels = max (channels, original_region->sources().size()); /* it will go above the layer of the highest existing region */ - layer = max (layer, original_region->layer ()); + layer = max (layer, original_region->layer()); } pl->in_partition = false; @@ -3252,32 +3099,19 @@ Playlist::combine (const RegionList& r) /* now create a new PlaylistSource for each channel in the new playlist */ -<<<<<<< HEAD + SourceList sources; - pair extent = pl->_get_extent (); -======= -<<<<<<< HEAD -<<<<<<< HEAD - SourceList sources; - pair extent = pl->_get_extent (); -======= - SourceList sources; - pair extent = pl->get_extent(); ->>>>>>> Revert "NO-OP: code formatting and cleanup, thanks clang-format" -======= - SourceList sources; - pair extent = pl->get_extent(); ->>>>>>> Revert "NO-OP: code formatting and cleanup, thanks clang-format" ->>>>>>> 0bbe6796b9 (Revert "NO-OP: code formatting and cleanup, thanks clang-format") + pair extent = pl->get_extent(); + timepos_t zero (_type == DataType::AUDIO ? Temporal::AudioTime : Temporal::BeatTime); for (uint32_t chn = 0; chn < channels; ++chn) { - sources.push_back (SourceFactory::createFromPlaylist (_type, _session, pl, id (), parent_name, chn, 0, extent.second, false, false)); + sources.push_back (SourceFactory::createFromPlaylist (_type, _session, pl, id(), parent_name, chn, zero, extent.second, false, false)); } /* now a new whole-file region using the list of sources */ - plist.add (Properties::start, 0); - plist.add (Properties::length, extent.second); + plist.add (Properties::start, timecnt_t (0, zero)); + plist.add (Properties::length, timecnt_t (extent.second, extent.first)); plist.add (Properties::name, parent_name); plist.add (Properties::whole_file, true); @@ -3286,22 +3120,22 @@ Playlist::combine (const RegionList& r) /* now the non-whole-file region that we will actually use in the playlist */ plist.clear (); - plist.add (Properties::start, 0); + plist.add (Properties::start, zero); plist.add (Properties::length, extent.second); plist.add (Properties::name, child_name); - plist.add (Properties::layer, layer + 1); + plist.add (Properties::layer, layer+1); boost::shared_ptr compound_region = RegionFactory::create (parent_region, plist, true, &thawlist); - for (SourceList::iterator s = sources.begin (); s != sources.end (); ++s) { - boost::dynamic_pointer_cast (*s)->set_owner (compound_region->id ()); + for (SourceList::iterator s = sources.begin(); s != sources.end(); ++s) { + boost::dynamic_pointer_cast(*s)->set_owner (compound_region->id()); } /* remove all the selected regions from the current playlist */ freeze (); - for (RegionList::const_iterator i = r.begin (); i != r.end (); ++i) { + for (RegionList::const_iterator i = r.begin(); i != r.end(); ++i) { remove_region (*i); } @@ -3337,8 +3171,8 @@ Playlist::uncombine (boost::shared_ptr target) pl = pls->playlist (); - samplepos_t adjusted_start = 0; /* gcc isn't smart enough */ - samplepos_t adjusted_end = 0; /* gcc isn't smart enough */ + timepos_t adjusted_start; + timepos_t adjusted_end; /* the leftmost (earliest) edge of the compound region * starts at zero in its source, or larger if it @@ -3351,9 +3185,9 @@ Playlist::uncombine (boost::shared_ptr target) /* (2) get all the original regions */ - const RegionList& rl (pl->region_list_property ().rlist ()); - RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations ()); - sampleoffset_t move_offset = 0; + const RegionList& rl (pl->region_list_property().rlist()); + RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations()); + timecnt_t move_offset; /* there are three possibilities here: 1) the playlist that the playlist source was based on @@ -3370,33 +3204,22 @@ Playlist::uncombine (boost::shared_ptr target) the original regions, and add them instead. */ -<<<<<<< HEAD - const bool need_copies = (boost::dynamic_pointer_cast (pls)->owner () != target->id ()) || - (pls->original () != id ()); -======= const bool need_copies = (boost::dynamic_pointer_cast (pls)->owner() != target->id()) || (pls->original() != id()); - for (RegionList::const_iterator i = rl.begin(); i != rl.end(); ++i) { -<<<<<<< HEAD ->>>>>>> 0bbe6796b9 (Revert "NO-OP: code formatting and cleanup, thanks clang-format") + + const bool need_copies = (boost::dynamic_pointer_cast (pls)->owner() != target->id()) || + (pls->original() != id()); + ThawList thawlist; for (RegionList::const_iterator i = rl.begin (); i != rl.end (); ++i) { -<<<<<<< HEAD -======= -======= ->>>>>>> Revert "NO-OP: code formatting and cleanup, thanks clang-format" -======= - ->>>>>>> Revert "NO-OP: code formatting and cleanup, thanks clang-format" ->>>>>>> 0bbe6796b9 (Revert "NO-OP: code formatting and cleanup, thanks clang-format") boost::shared_ptr current (*i); RegionFactory::CompoundAssociations::iterator ca = cassocs.find (*i); - if (ca == cassocs.end ()) { + if (ca == cassocs.end()) { continue; } @@ -3404,32 +3227,16 @@ Playlist::uncombine (boost::shared_ptr target) bool modified_region; - if (i == rl.begin ()) { - move_offset = (target->position () - original->position ()) - target->start (); - adjusted_start = original->position () + target->start (); - adjusted_end = adjusted_start + target->length (); + if (i == rl.begin()) { + move_offset = original->position().distance (target->position()) - timecnt_t (target->start(), target->position()); + adjusted_start = original->position() + target->start(); + adjusted_end = adjusted_start + target->length(); } -<<<<<<< HEAD -======= -<<<<<<< HEAD -<<<<<<< HEAD ->>>>>>> 0bbe6796b9 (Revert "NO-OP: code formatting and cleanup, thanks clang-format") if (!need_copies) { thawlist.add (original); } else { - samplepos_t pos = original->position (); -<<<<<<< HEAD -======= -======= - if (need_copies) { - samplepos_t pos = original->position(); ->>>>>>> Revert "NO-OP: code formatting and cleanup, thanks clang-format" -======= - if (need_copies) { - samplepos_t pos = original->position(); ->>>>>>> Revert "NO-OP: code formatting and cleanup, thanks clang-format" ->>>>>>> 0bbe6796b9 (Revert "NO-OP: code formatting and cleanup, thanks clang-format") + timepos_t pos = original->position(); /* make a copy, but don't announce it */ original = RegionFactory::create (original, false, false, &thawlist); /* the pure copy constructor resets position() to zero, so fix that up. */ @@ -3445,42 +3252,42 @@ Playlist::uncombine (boost::shared_ptr target) modified_region = false; switch (original->coverage (adjusted_start, adjusted_end)) { - case Evoral::OverlapNone: - /* original region does not cover any part + case Temporal::OverlapNone: + /* original region does not cover any part * of the current state of the compound region */ - continue; + continue; - case Evoral::OverlapInternal: - /* overlap is just a small piece inside the + case Temporal::OverlapInternal: + /* overlap is just a small piece inside the * original so trim both ends */ - original->trim_to (adjusted_start, adjusted_end - adjusted_start); - modified_region = true; - break; + original->trim_to (adjusted_start, adjusted_start.distance (adjusted_end)); + modified_region = true; + break; - case Evoral::OverlapExternal: - /* overlap fully covers original, so leave it as is */ - break; + case Temporal::OverlapExternal: + /* overlap fully covers original, so leave it as is */ + break; - case Evoral::OverlapEnd: - /* overlap starts within but covers end, so trim the front of the region */ - original->trim_front (adjusted_start); - modified_region = true; - break; + case Temporal::OverlapEnd: + /* overlap starts within but covers end, so trim the front of the region */ + original->trim_front (adjusted_start); + modified_region = true; + break; - case Evoral::OverlapStart: - /* overlap covers start but ends within, so + case Temporal::OverlapStart: + /* overlap covers start but ends within, so * trim the end of the region. */ - original->trim_end (adjusted_end); - modified_region = true; - break; + original->trim_end (adjusted_end); + modified_region = true; + break; } - if (move_offset) { + if (!move_offset.zero()) { /* fix the position to match any movement of the compound region. */ - original->set_position (original->position () + move_offset); + original->set_position (original->position() + move_offset); modified_region = true; } @@ -3501,17 +3308,17 @@ Playlist::uncombine (boost::shared_ptr target) in_partition = true; freeze (); - /* (3) remove the compound region */ + // (3) remove the compound region remove_region (target); - /* (4) add the constituent regions */ + // (4) add the constituent regions - for (vector >::iterator i = originals.begin (); i != originals.end (); ++i) { - add_region ((*i), (*i)->position ()); - set_layer ((*i), (*i)->layer ()); - if (!RegionFactory::region_by_id ((*i)->id ())) { - RegionFactory::map_add (*i); + for (vector >::iterator i = originals.begin(); i != originals.end(); ++i) { + add_region ((*i), (*i)->position()); + set_layer((*i), (*i)->layer()); + if (!RegionFactory::region_by_id((*i)->id())) { + RegionFactory::map_add(*i); } } @@ -3521,16 +3328,16 @@ Playlist::uncombine (boost::shared_ptr target) } void -Playlist::fade_range (list& ranges) +Playlist::fade_range (list& ranges) { RegionReadLock rlock (this); - for (list::iterator r = ranges.begin (); r != ranges.end ();) { - list::iterator tmpr = r; + for (list::iterator r = ranges.begin(); r != ranges.end(); ) { + list::iterator tmpr = r; ++tmpr; for (RegionList::const_iterator i = regions.begin (); i != regions.end ();) { RegionList::const_iterator tmpi = i; ++tmpi; - (*i)->fade_range ((*r).start, (*r).end); + (*i)->fade_range ((*r).start().samples(), (*r).end().samples()); i = tmpi; } r = tmpr; @@ -3607,7 +3414,7 @@ Playlist::reset_shares () * check_crossfades for each one. */ void -Playlist::coalesce_and_check_crossfades (list > ranges) +Playlist::coalesce_and_check_crossfades (list ranges) { /* XXX: it's a shame that this coalesce algorithm also exists in * TimeSelection::consolidate(). @@ -3616,16 +3423,17 @@ Playlist::coalesce_and_check_crossfades (list > range /* XXX: xfade: this is implemented in Evoral::RangeList */ restart: - for (list >::iterator i = ranges.begin (); i != ranges.end (); ++i) { - for (list >::iterator j = ranges.begin (); j != ranges.end (); ++j) { + for (list::iterator i = ranges.begin(); i != ranges.end(); ++i) { + for (list::iterator j = ranges.begin(); j != ranges.end(); ++j) { + if (i == j) { continue; } - /* XXX i->from can be > i->to - is this right? coverage() will return OverlapNone in this case */ - if (Evoral::coverage (i->from, i->to, j->from, j->to) != Evoral::OverlapNone) { - i->from = min (i->from, j->from); - i->to = max (i->to, j->to); + // XXX i->from can be > i->to - is this right? coverage() will return OverlapNone in this case + if (Temporal::coverage_exclusive_ends (i->start(), i->end(), j->start(), j->start()) != Temporal::OverlapNone) { + i->set_start (min (i->start(), j->start())); + i->set_end (max (i->end(), j->end())); ranges.erase (j); goto restart; } diff --git a/libs/ardour/playlist_factory.cc b/libs/ardour/playlist_factory.cc index b535f84506..f5dbc41a1b 100644 --- a/libs/ardour/playlist_factory.cc +++ b/libs/ardour/playlist_factory.cc @@ -110,7 +110,7 @@ PlaylistFactory::create (boost::shared_ptr old, string name, boo } boost::shared_ptr -PlaylistFactory::create (boost::shared_ptr old, samplepos_t start, samplecnt_t cnt, string name, bool hidden) +PlaylistFactory::create (boost::shared_ptr old, timepos_t const & start, timepos_t const & cnt, string name, bool hidden) { boost::shared_ptr pl; boost::shared_ptr apl; diff --git a/libs/ardour/playlist_source.cc b/libs/ardour/playlist_source.cc index dbc74b41a6..f3cc71d254 100644 --- a/libs/ardour/playlist_source.cc +++ b/libs/ardour/playlist_source.cc @@ -43,7 +43,7 @@ using namespace ARDOUR; using namespace PBD; PlaylistSource::PlaylistSource (Session& s, const ID& orig, const std::string& name, boost::shared_ptr p, DataType type, - sampleoffset_t begin, samplecnt_t len, Source::Flag /*flags*/) + timepos_t const & begin, timepos_t const & len, Source::Flag /*flags*/) : Source (s, type, name) , _playlist (p) , _original (orig) diff --git a/libs/ardour/plugin_insert.cc b/libs/ardour/plugin_insert.cc index dcf9b27f00..d6433d838e 100644 --- a/libs/ardour/plugin_insert.cc +++ b/libs/ardour/plugin_insert.cc @@ -310,7 +310,7 @@ PluginInsert::control_list_automation_state_changed (Evoral::Parameter which, Au = boost::dynamic_pointer_cast(control (which)); if (c && s != Off) { - _plugins[0]->set_parameter (which.id(), c->list()->eval (_session.transport_sample()), 0); + _plugins[0]->set_parameter (which.id(), c->list()->eval (timepos_t (_session.transport_sample())), 0) } } @@ -516,7 +516,8 @@ PluginInsert::create_automatable_parameters () const bool automatable = a.find(param) != a.end(); - boost::shared_ptr list(new AutomationList(param, desc)); +#warning NUTEMPO question : how to decide the right time domain here? + boost::shared_ptr list(new AutomationList(param, desc, Temporal::AudioTime)); boost::shared_ptr c (new PluginControl(this, param, desc, list)); if (!automatable || (limit_automatables > 0 && what_can_be_automated ().size() > limit_automatables)) { c->set_flag (Controllable::NotAutomatable); @@ -536,7 +537,8 @@ PluginInsert::create_automatable_parameters () if (desc.datatype != Variant::NOTHING) { boost::shared_ptr list; if (Variant::type_is_numeric(desc.datatype)) { - list = boost::shared_ptr(new AutomationList(param, desc)); +#warning NUTEMPO question : how to decide the right time domain here? + list = boost::shared_ptr(new AutomationList(param, desc, Temporal::AudioTime)); } boost::shared_ptr c (new PluginPropertyControl(this, param, desc, list)); if (!Variant::type_is_numeric(desc.datatype)) { @@ -558,7 +560,8 @@ PluginInsert::create_automatable_parameters () desc.normal = 1; desc.lower = 0; desc.upper = 1; - boost::shared_ptr list(new AutomationList(param, desc)); +#warning NUTEMPO question : how to decide the right time domain here? + boost::shared_ptr list(new AutomationList(param, desc, Temporal::AudioTime)); boost::shared_ptr c (new PluginControl(this, param, desc, list)); add_control (c); } @@ -644,8 +647,8 @@ PluginInsert::automation_run (samplepos_t start, pframes_t nframes, bool only_ac { // XXX does not work when rolling backwards if (_loop_location && nframes > 0) { - const samplepos_t loop_start = _loop_location->start (); - const samplepos_t loop_end = _loop_location->end (); + const samplepos_t loop_start = _loop_location->start_sample (); + const samplepos_t loop_end = _loop_location->end_sample (); const samplecnt_t looplen = loop_end - loop_start; samplecnt_t remain = nframes; @@ -668,15 +671,12 @@ PluginInsert::automation_run (samplepos_t start, pframes_t nframes, bool only_ac } bool -PluginInsert::find_next_event (double now, double end, Evoral::ControlEvent& next_event, bool only_active) const +PluginInsert::find_next_event (timepos_t const & now, timepos_t const & end, Evoral::ControlEvent& next_event, bool only_active) const { bool rv = Automatable::find_next_event (now, end, next_event, only_active); if (_loop_location && now < end) { - if (rv) { - end = ceil (next_event.when); - } - const samplepos_t loop_end = _loop_location->end (); + const timepos_t loop_end = _loop_location->end (); assert (now < loop_end); // due to map_loop_range () if (end > loop_end) { next_event.when = loop_end; @@ -932,7 +932,8 @@ PluginInsert::connect_and_run (BufferSet& bufs, samplepos_t start, samplepos_t e if (clist && (static_cast (*clist)).automation_playback ()) { /* 1. Set value at [sub]cycle start */ bool valid; - float val = clist->rt_safe_eval (start, valid); + float val = c.list()->rt_safe_eval (timepos_t (start), valid); + if (valid) { c.set_value_unchecked(val); } @@ -1336,7 +1337,7 @@ PluginInsert::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sa void PluginInsert::automate_and_run (BufferSet& bufs, samplepos_t start, samplepos_t end, double speed, pframes_t nframes) { - Evoral::ControlEvent next_event (0, 0.0f); + Evoral::ControlEvent next_event (timepos_t (Temporal::AudioTime), 0.0f); samplecnt_t offset = 0; Glib::Threads::Mutex::Lock lm (control_lock(), Glib::Threads::TRY_LOCK); @@ -1349,9 +1350,9 @@ PluginInsert::automate_and_run (BufferSet& bufs, samplepos_t start, samplepos_t /* map start back into loop-range, adjust end */ map_loop_range (start, end); - bool no_split_cycle =_plugins.front()->requires_fixed_sized_buffers () || _plugins.front()->get_info ()->type == ARDOUR::VST3; + const bool no_split_cycle =_plugins.front()->requires_fixed_sized_buffers () || _plugins.front()->get_info ()->type == ARDOUR::VST3; - if (no_split_cycle || !find_next_event (start, end, next_event)) { + if (no_split_cycle || !find_next_event (timepos_t (start), timepos_t (end), next_event)) { /* no events have a time within the relevant range */ @@ -1361,7 +1362,7 @@ PluginInsert::automate_and_run (BufferSet& bufs, samplepos_t start, samplepos_t while (nframes) { - samplecnt_t cnt = min ((samplecnt_t) ceil (fabs (next_event.when - start)), (samplecnt_t) nframes); + samplecnt_t cnt = min (timepos_t (start).distance (next_event.when).samples(), (samplecnt_t) nframes); assert (cnt > 0); connect_and_run (bufs, start, start + cnt * speed, speed, cnt, offset, true); @@ -1372,7 +1373,7 @@ PluginInsert::automate_and_run (BufferSet& bufs, samplepos_t start, samplepos_t map_loop_range (start, end); - if (!find_next_event (start, end, next_event)) { + if (!find_next_event (timepos_t (start), timepos_t (end), next_event)) { break; } } @@ -3363,7 +3364,7 @@ PluginInsert::start_touch (uint32_t param_id) boost::shared_ptr ac = automation_control (Evoral::Parameter (PluginAutomation, 0, param_id)); if (ac) { // ToDo subtract _plugin_signal_latency from audible_sample() when rolling, assert > 0 - ac->start_touch (session().audible_sample()); + ac->start_touch (timepos_t (session().audible_sample())); } } @@ -3373,7 +3374,7 @@ PluginInsert::end_touch (uint32_t param_id) boost::shared_ptr ac = automation_control (Evoral::Parameter (PluginAutomation, 0, param_id)); if (ac) { // ToDo subtract _plugin_signal_latency from audible_sample() when rolling, assert > 0 - ac->stop_touch (session().audible_sample()); + ac->stop_touch (timepos_t (session().audible_sample())); } } diff --git a/libs/ardour/processor.cc b/libs/ardour/processor.cc index a99d09049a..6d9cb7275d 100644 --- a/libs/ardour/processor.cc +++ b/libs/ardour/processor.cc @@ -292,12 +292,12 @@ Processor::map_loop_range (samplepos_t& start, samplepos_t& end) const return false; } - const samplepos_t loop_end = _loop_location->end (); + const samplepos_t loop_end = _loop_location->end().samples (); if (start < loop_end) { return false; } - const samplepos_t loop_start = _loop_location->start (); + const samplepos_t loop_start = _loop_location->start().samples (); const samplecnt_t looplen = loop_end - loop_start; const sampleoffset_t start_off = (start - loop_start) % looplen; const samplepos_t start_pos = loop_start + start_off; diff --git a/libs/ardour/quantize.cc b/libs/ardour/quantize.cc index 0a7bb1b48a..0677a03fc1 100644 --- a/libs/ardour/quantize.cc +++ b/libs/ardour/quantize.cc @@ -38,7 +38,7 @@ using namespace ARDOUR; */ Quantize::Quantize (bool snap_start, bool snap_end, - double start_grid, double end_grid, + int start_grid, int end_grid, float strength, float swing, Temporal::Beats const & threshold) : _snap_start (snap_start) , _snap_end (snap_end) @@ -116,14 +116,12 @@ Quantize::operator () (boost::shared_ptr model, Temporal::Beats position, std::vector::Notes>& seqs) { - /* TODO: Rewrite this to be precise with fixed point? */ - /* Calculate offset from start of model to next closest quantize step, to quantize relative to actual session beats (etc.) rather than from the start of the model. */ - const double round_pos = (position / _start_grid) * _start_grid; - const double offset = round_pos - position; + const Temporal::Beats round_pos = (position / _start_grid) * _start_grid; + const Temporal::Beats offset = round_pos - position; MidiModel::NoteDiffCommand* cmd = new MidiModel::NoteDiffCommand (model, "quantize"); @@ -158,9 +156,9 @@ Quantize::operator () (boost::shared_ptr model, if (delta.abs() >= _threshold) { if (_snap_start) { - delta = delta * _strength; - cmd->change ((*i), MidiModel::NoteDiffCommand::StartTime, - (*i)->time() + delta); + /* this is here because Beats intentionally does not have operator* (double) */ + delta = Temporal::Beats::ticks (llrintf (delta.to_ticks()) * _strength); + cmd->change ((*i), MidiModel::NoteDiffCommand::StartTime, (*i)->time() + delta); } } diff --git a/libs/ardour/rb_effect.cc b/libs/ardour/rb_effect.cc index c37541b91f..95ef38471d 100644 --- a/libs/ardour/rb_effect.cc +++ b/libs/ardour/rb_effect.cc @@ -148,8 +148,8 @@ RBEffect::run (boost::shared_ptr r, Progress* progress) * I hope this is clear. */ - double stretch = region->stretch () * tsr.time_fraction; - double shift = region->shift () * tsr.pitch_fraction; + double stretch = tsr.time_fraction * region->stretch (); + double shift = tsr.pitch_fraction * region->shift (); samplecnt_t read_start = region->ancestral_start_sample () + samplecnt_t (region->start_sample () / (double)region->stretch ()); @@ -352,21 +352,21 @@ RBEffect::run (boost::shared_ptr r, Progress* progress) /* now reset ancestral data for each new region */ for (vector >::iterator x = results.begin (); x != results.end (); ++x) { - (*x)->set_ancestral_data (timecnt_t::from_samples (read_start), - timecnt_t::from_samples (read_duration, timepos_t::from_samples (read_start)), + (*x)->set_ancestral_data (timecnt_t (read_start), + timecnt_t (read_duration, timepos_t (read_start)), stretch, shift); (*x)->set_master_sources (region->master_sources ()); /* multiply the old (possibly previously stretched) region length by the extra * stretch this time around to get its new length. this is a non-music based edit atm. */ - (*x)->set_length (timecnt_t::from_samples (samplepos_t ((*x)->length_samples () * tsr.time_fraction), (*x)->nt_position())); + (*x)->set_length (timecnt_t (tsr.time_fraction * (*x)->length_samples (), (*x)->nt_position())); } /* stretch region gain envelope */ /* XXX: assuming we've only processed one input region into one result here */ - if (ret == 0 && tsr.time_fraction != 1) { + if (ret == 0 && !tsr.time_fraction.is_unity()) { boost::shared_ptr result = boost::dynamic_pointer_cast (results.front ()); assert (result); result->envelope ()->x_scale (tsr.time_fraction); diff --git a/libs/ardour/readable.cc b/libs/ardour/readable.cc index 0390a0169d..b24e40edbb 100644 --- a/libs/ardour/readable.cc +++ b/libs/ardour/readable.cc @@ -30,10 +30,10 @@ using namespace ARDOUR; -std::vector > -Readable::load (Session& session, std::string const& path) +std::vector > +AudioReadable::load (Session& session, std::string const& path) { - std::vector > readables; + std::vector > readables; ARDOUR::SoundFileInfo sf_info; std::string error_msg; diff --git a/libs/ardour/record_enable_control.cc b/libs/ardour/record_enable_control.cc index a789b39e11..f079b699cb 100644 --- a/libs/ardour/record_enable_control.cc +++ b/libs/ardour/record_enable_control.cc @@ -24,9 +24,10 @@ using namespace ARDOUR; using namespace PBD; +#warning NUTEMPO QUESTION what time domain should this really use? RecordEnableControl::RecordEnableControl (Session& session, std::string const & name, Recordable& r) : SlavableAutomationControl (session, RecEnableAutomation, ParameterDescriptor (RecEnableAutomation), - boost::shared_ptr(new AutomationList(Evoral::Parameter(RecEnableAutomation))), + boost::shared_ptr(new AutomationList(Evoral::Parameter(RecEnableAutomation), Temporal::AudioTime)), name) , _recordable (r) { diff --git a/libs/ardour/record_safe_control.cc b/libs/ardour/record_safe_control.cc index 6fce4f028e..c645f452e3 100644 --- a/libs/ardour/record_safe_control.cc +++ b/libs/ardour/record_safe_control.cc @@ -24,9 +24,10 @@ using namespace ARDOUR; using namespace PBD; +#warning NUTEMPO question: what is the right time domain here RecordSafeControl::RecordSafeControl (Session& session, std::string const & name, Recordable& r) : SlavableAutomationControl (session, RecSafeAutomation, ParameterDescriptor (RecSafeAutomation), - boost::shared_ptr(new AutomationList(Evoral::Parameter(RecSafeAutomation))), + boost::shared_ptr(new AutomationList(Evoral::Parameter(RecSafeAutomation), Temporal::AudioTime)), name) , _recordable (r) { diff --git a/libs/ardour/region.cc b/libs/ardour/region.cc index aa48f3363f..877655a3c7 100644 --- a/libs/ardour/region.cc +++ b/libs/ardour/region.cc @@ -79,7 +79,6 @@ namespace ARDOUR { PBD::PropertyDescriptor ancestral_length; PBD::PropertyDescriptor stretch; PBD::PropertyDescriptor shift; - PBD::PropertyDescriptor position_lock_style; PBD::PropertyDescriptor layering_index; PBD::PropertyDescriptor tags; PBD::PropertyDescriptor contents; @@ -139,8 +138,6 @@ Region::make_property_quarks () DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for stretch = %1\n", Properties::stretch.property_id)); Properties::shift.property_id = g_quark_from_static_string (X_("shift")); DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for shift = %1\n", Properties::shift.property_id)); - Properties::position_lock_style.property_id = g_quark_from_static_string (X_("positional-lock-style")); - DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for position_lock_style = %1\n", Properties::position_lock_style.property_id)); Properties::layering_index.property_id = g_quark_from_static_string (X_("layering-index")); DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for layering_index = %1\n", Properties::layering_index.property_id)); Properties::tags.property_id = g_quark_from_static_string (X_("tags")); @@ -176,7 +173,6 @@ Region::register_properties () add_property (_ancestral_length); add_property (_stretch); add_property (_shift); - add_property (_position_lock_style); add_property (_layering_index); add_property (_tags); add_property (_contents); @@ -209,7 +205,6 @@ Region::register_properties () , _ancestral_length (Properties::ancestral_length, (l)) \ , _stretch (Properties::stretch, 1.0) \ , _shift (Properties::shift, 1.0) \ - , _position_lock_style (Properties::position_lock_style, _type == DataType::AUDIO ? AudioTime : MusicTime) \ , _layering_index (Properties::layering_index, 0) \ , _tags (Properties::tags, "") \ , _contents (Properties::contents, false) @@ -243,7 +238,6 @@ Region::register_properties () , _ancestral_length (Properties::ancestral_length, other->_ancestral_length) \ , _stretch (Properties::stretch, other->_stretch) \ , _shift (Properties::shift, other->_shift) \ - , _position_lock_style (Properties::position_lock_style, other->_position_lock_style) \ , _layering_index (Properties::layering_index, other->_layering_index) \ , _tags (Properties::tags, other->_tags) \ , _contents (Properties::contents, other->_contents) @@ -310,7 +304,6 @@ Region::Region (boost::shared_ptr other) use_sources (other->_sources); set_master_sources (other->_master_sources); - _position_lock_style = other->_position_lock_style.val(); _first_edit = other->_first_edit; _start = other->_start; @@ -478,7 +471,7 @@ Region::set_length (timecnt_t const & len) * length impossible. */ - if (timepos_t::max().earlier (len) < _position) { + if (timepos_t::max (len.time_domain()).earlier (len) < _position) { return; } @@ -579,16 +572,11 @@ Region::special_set_position (timepos_t const & pos) } void -Region::set_position_lock_style (PositionLockStyle ps) +Region::recompute_position_from_time_domain () { - if (_position_lock_style != ps) { - - boost::shared_ptr pl (playlist()); - - _position_lock_style = ps; - - send_change (Properties::position_lock_style); - } + /* XXX currently do nothing, but if we wanted to reduce lazy evaluation + * of timepos_t non-canonical values, we could possibly do it here. + */ } void @@ -604,13 +592,23 @@ Region::update_after_tempo_map_change (bool send) return; } + if (!send) { + return; + } + + PropertyChange what_changed; + +#warning NUTEMPO THINKME make this more nuanced ... nothing may have changed and maybe we don't need this at all + + what_changed.add (Properties::start); + what_changed.add (Properties::length); + what_changed.add (Properties::position); + /* do this even if the position is the same. this helps out * a GUI that has moved its representation already. */ - if (send) { - send_change (Properties::position); - } + send_change (what_changed); } void @@ -636,7 +634,7 @@ Region::set_position (timepos_t const & pos) * given that we already are notifying about position change. */ - if (position_lock_style() != AudioTime) { + if (position_time_domain() != Temporal::AudioTime) { p_and_l.add (Properties::length); } @@ -664,9 +662,9 @@ Region::set_position_internal (timepos_t const & pos) * * XXX is this the right thing to do? */ - if (timepos_t::max().earlier (_length) < _position) { + if (timepos_t::max (_length.val().time_domain()).earlier (_length) < _position) { _last_length = _length; - _length = _position.call().distance (timepos_t::max()); + _length = _position.call().distance (timepos_t::max(_position.val().time_domain())); } } } @@ -692,12 +690,12 @@ Region::set_initial_position (timepos_t const & pos) * XXX is this the right thing to do? */ - if (timepos_t::max().earlier (_length) < _position) { + if (timepos_t::max (_length.val().time_domain()).earlier (_length) < _position) { _last_length = _length; - _length = _position.call().distance (timepos_t::max()); + _length = _position.call().distance (timepos_t::max (_position.val().time_domain())); } - recompute_position_from_lock_style (); + recompute_position_from_time_domain (); /* ensure that this move doesn't cause a range move */ _last_position = _position; _last_length.set_position (_position); @@ -710,14 +708,6 @@ Region::set_initial_position (timepos_t const & pos) send_change (Properties::position); } -void -Region::recompute_position_from_lock_style () -{ - /* XXX currently do nothing, but if we wanted to reduce lazy evaluation - * of timepos_t non-canonical values, we could possibly do it here. - */ -} - void Region::nudge_position (timecnt_t const & n) { @@ -732,8 +722,8 @@ Region::nudge_position (timecnt_t const & n) timepos_t new_position = _position; if (n.positive()) { - if (nt_position() > timepos_t::max().earlier (n)) { - new_position = timepos_t::max(); + if (nt_position() > timepos_t::max (n.time_domain()).earlier (n)) { + new_position = timepos_t::max (n.time_domain()); } else { new_position += n; } @@ -939,7 +929,7 @@ Region::trim_to (timepos_t const & position, timecnt_t const & length) void Region::trim_to_internal (timepos_t const & position, timecnt_t const & length) { - timecnt_t new_start; + timecnt_t new_start (length.time_domain()); if (locked()) { return; @@ -1156,7 +1146,7 @@ Region::adjust_to_sync (timepos_t const & pos) const p = 0; } } else { - if (timepos_t::max().earlier (timecnt_t (p, p)) > offset) { + if (timepos_t::max (p.time_domain()).earlier (timecnt_t (p, p)) > offset) { p += offset; } } @@ -1334,10 +1324,10 @@ Region::_set_state (const XMLNode& node, int /*version*/, PropertyChange& what_c */ if (!_sources.empty() && _type == DataType::AUDIO) { - if ((nt_length().time_domain() == Temporal::AudioTime) && (length_samples() > _sources.front()->length(position_sample()))) { #warning NUTEMPO FIXME do this better - //_length = Temporal::samples_to_superclock (_sources.front()->length(position_sample()) - start_sample(), Temporal::_thread_sample_rate); - } + // if ((nt_length().time_domain() == Temporal::AudioTime) && (length_samples() > _sources.front()->length(position_sample()))) { + //_length = Temporal::samples_to_superclock (_sources.front()->length(position_sample()) - start_sample(), Temporal::_thread_sample_rate); + //} } set_id (node); @@ -1425,14 +1415,14 @@ Region::send_change (const PropertyChange& what_changed) bool Region::overlap_equivalent (boost::shared_ptr other) const { - return coverage (other->first_sample(), other->last_sample()) != Evoral::OverlapNone; + return coverage (other->nt_position(), other->nt_last()) != Temporal::OverlapNone; } bool Region::enclosed_equivalent (boost::shared_ptr other) const { - return (first_sample() >= other->first_sample() && last_sample() <= other->last_sample()) || - (first_sample() <= other->first_sample() && last_sample() >= other->last_sample()) ; + return ((nt_position() >= other->nt_position() && nt_end() <= other->nt_end()) || + (nt_position() <= other->nt_position() && nt_end() >= other->nt_end())); } bool @@ -1947,11 +1937,6 @@ Region::is_compound () const return max_source_level() > 0; } -void -Region::post_set (const PropertyChange& pc) -{ -} - void Region::set_start_internal (timecnt_t const & s) { diff --git a/libs/ardour/region_factory.cc b/libs/ardour/region_factory.cc index 6452462377..3215ca93ae 100644 --- a/libs/ardour/region_factory.cc +++ b/libs/ardour/region_factory.cc @@ -91,8 +91,8 @@ RegionFactory::create (boost::shared_ptr region, bool announce, bo ret->set_name (new_region_name (ret->name ())); - if (ret->session ().config.get_glue_new_regions_to_bars_and_beats () && ret->position_lock_style () != MusicTime) { - ret->set_position_lock_style (MusicTime); + if (ret->session().config.get_glue_new_regions_to_bars_and_beats() && ret->position_time_domain() != Temporal::BeatTime) { + ret->set_position_time_domain (Temporal::BeatTime); } /* pure copy constructor - no property list */ @@ -133,8 +133,8 @@ RegionFactory::create (boost::shared_ptr region, const PropertyList& pli ret->apply_changes (plist); - if (ret->session ().config.get_glue_new_regions_to_bars_and_beats () && ret->position_lock_style () != MusicTime) { - ret->set_position_lock_style (MusicTime); + if (ret->session().config.get_glue_new_regions_to_bars_and_beats() && ret->position_time_domain() != Temporal::BeatTime) { + ret->set_position_time_domain (Temporal::BeatTime); } if (announce) { @@ -173,8 +173,8 @@ RegionFactory::create (boost::shared_ptr region, timecnt_t const & offse } ret->apply_changes (plist); - if (ret->session ().config.get_glue_new_regions_to_bars_and_beats () && ret->position_lock_style () != MusicTime) { - ret->set_position_lock_style (MusicTime); + if (ret->session().config.get_glue_new_regions_to_bars_and_beats() && ret->position_time_domain() != Temporal::BeatTime) { + ret->set_position_time_domain (Temporal::BeatTime); } if (announce) { @@ -215,8 +215,8 @@ RegionFactory::create (boost::shared_ptr region, const SourceList& srcs, ret->apply_changes (plist); - if (ret->session ().config.get_glue_new_regions_to_bars_and_beats () && ret->position_lock_style () != MusicTime) { - ret->set_position_lock_style (MusicTime); + if (ret->session().config.get_glue_new_regions_to_bars_and_beats() && ret->position_time_domain() != Temporal::BeatTime) { + ret->set_position_time_domain (Temporal::BeatTime); } if (announce) { @@ -258,8 +258,8 @@ RegionFactory::create (const SourceList& srcs, const PropertyList& plist, bool a ret->apply_changes (plist); - if (ret->session ().config.get_glue_new_regions_to_bars_and_beats () && ret->position_lock_style () != MusicTime) { - ret->set_position_lock_style (MusicTime); + if (ret->session().config.get_glue_new_regions_to_bars_and_beats() && ret->position_time_domain() != Temporal::BeatTime) { + ret->set_position_time_domain (Temporal::BeatTime); } if (announce) { diff --git a/libs/ardour/return.cc b/libs/ardour/return.cc index e22e479116..17365377fb 100644 --- a/libs/ardour/return.cc +++ b/libs/ardour/return.cc @@ -52,7 +52,8 @@ Return::Return (Session& s, bool internal) { /* never muted */ - boost::shared_ptr gl (new AutomationList (Evoral::Parameter (GainAutomation))); +#warning NUTEMPO QUESTION what time domain shoudl this really use? + boost::shared_ptr gl (new AutomationList (Evoral::Parameter (GainAutomation), Temporal::AudioTime)); _gain_control = boost::shared_ptr (new GainControl (_session, Evoral::Parameter (GainAutomation), gl)); add_control (_gain_control); diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index 49ba9757f7..f4210c22fc 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -4414,7 +4414,7 @@ Route::protect_automation () */ void -Route::shift (samplepos_t pos, samplecnt_t samples) +Route::shift (timepos_t const & pos, timecnt_t const & distance) { /* pan automation */ if (_pannable) { @@ -4425,7 +4425,7 @@ Route::shift (samplepos_t pos, samplecnt_t samples) if (pc) { boost::shared_ptr al = pc->alist(); XMLNode& before = al->get_state (); - al->shift (pos, samples); + al->shift (pos, timecnt_t (distance)); XMLNode& after = al->get_state (); _session.add_command (new MementoCommand (*al.get(), &before, &after)); } @@ -4449,7 +4449,7 @@ Route::shift (samplepos_t pos, samplecnt_t samples) continue; } XMLNode &before = al->get_state (); - al->shift (pos, samples); + al->shift (pos, distance); XMLNode &after = al->get_state (); _session.add_command (new MementoCommand (*al.get(), &before, &after)); } diff --git a/libs/ardour/send.cc b/libs/ardour/send.cc index 1572e799b5..08461cd23c 100644 --- a/libs/ardour/send.cc +++ b/libs/ardour/send.cc @@ -95,7 +95,8 @@ Send::Send (Session& s, boost::shared_ptr p, boost::shared_ptr gl (new AutomationList (Evoral::Parameter (BusSendLevel))); +#warning NUTEMPO question what time domain should this use? + boost::shared_ptr gl (new AutomationList (Evoral::Parameter (BusSendLevel), Temporal::AudioTime)); _gain_control = boost::shared_ptr (new GainControl (_session, Evoral::Parameter(BusSendLevel), gl)); _gain_control->set_flag (Controllable::InlineControl); add_control (_gain_control); diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index 1057666596..a79dbd66f1 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -1,4 +1,4 @@ -/* +s/* * Copyright (C) 1999-2019 Paul Davis * Copyright (C) 2006-2007 Jesse Chappell * Copyright (C) 2006-2009 Sampo Savolainen @@ -180,6 +180,7 @@ Session::Session (AudioEngine &eng, : _playlists (new SessionPlaylists) , _engine (eng) , process_function (&Session::process_with_events) +#if 1 , _bounce_processing_active (false) , waiting_for_sync_offset (false) , _base_sample_rate (0) @@ -294,8 +295,8 @@ Session::Session (AudioEngine &eng, , _clicks_cleared (0) , _count_in_samples (0) , _play_range (false) - , _range_selection (-1,-1) - , _object_selection (-1,-1) + , _range_selection (timepos_t::max (Temporal::AudioTime), timepos_t::max (Temporal::AudioTime)) + , _object_selection (timepos_t::max (Temporal::AudioTime), timepos_t::max (Temporal::AudioTime)) , _preroll_record_trim_len (0) , _count_in_once (false) , main_outs (0) @@ -331,6 +332,152 @@ Session::Session (AudioEngine &eng, g_atomic_int_set (&_seek_counter, 0); g_atomic_int_set (&_butler_seek_counter, 0); +#if 0 + _bounce_processing_active = false; + waiting_for_sync_offset = false; + _base_sample_rate = 0; + _nominal_sample_rate = 0; + _current_sample_rate = 0; + _record_status = Disabled; + _transport_sample = 0; + _seek_counter = 0; + _session_range_location = 0; + _session_range_is_free = true; + _silent = false; + _remaining_latency_preroll = 0; + _engine_speed = 1.0; + _transport_speed = 0; + _default_transport_speed = 1.0; + _signalled_varispeed = 0; + auto_play_legal = false; + _requested_return_sample = -1; + current_block_size = 0; + _worst_output_latency = 0; + _worst_input_latency = 0; + _worst_route_latency = 0; + _send_latency_changes = 0; + _have_captured = false; + _non_soloed_outs_muted = false; + _listening = false; + _listen_cnt = 0; + _solo_isolated_cnt = 0; + _writable = false; + _under_nsm_control = false; + _xrun_count = 0; + master_wait_end = 0; + post_export_sync = false; + post_export_position = 0; + _exporting = false; + _export_rolling = false; + _realtime_export = false; + _region_export = false; + _export_preroll = 0; + _pre_export_mmc_enabled = false; + _name = snapshot_name; + _is_new = true; + _send_qf_mtc = false; + _pframes_since_last_mtc = 0; + play_loop = false; + loop_changing = false; + last_loopend = 0; + _session_dir = new SessionDirectory (fullpath); + _current_snapshot_name = snapshot_name; + state_tree = 0; + state_was_pending = false; + _state_of_the_state = StateOfTheState (CannotSave | InitialConnecting | Loading); + _suspend_save = 0; + _save_queued = false; + _save_queued_pending = false; + _last_roll_location = 0; + _last_roll_or_reversal_location = 0; + _last_record_location = 0; + pending_auto_loop = false; + lua = lua_newstate (&PBD::ReallocPool::lalloc, &_mempool); + _n_lua_scripts = 0; + _butler = new Butler (*this); + _transport_fsm = new TransportFSM (*this); + _post_transport_work = 0; + _locations = new Locations (*this); + _ignore_skips_updates = false; + _rt_thread_active = false; + _rt_emit_pending = false; + _ac_thread_active = 0; + _latency_recompute_pending = 0; + step_speed = 0; + outbound_mtc_timecode_frame = 0; + next_quarter_frame_to_send = -1; + _samples_per_timecode_frame = 0; + _frames_per_hour = 0; + _timecode_frames_per_hour = 0; + last_timecode_valid = false; + last_timecode_when = 0; + _send_timecode_update = false; + ltc_encoder = 0; + ltc_enc_buf= 0; + ltc_buf_off = 0; + ltc_buf_len = 0; + ltc_speed = 0; + ltc_enc_byte = 0; + ltc_enc_pos = 0; + ltc_enc_cnt = 0; + ltc_enc_off = 0; + restarting = false; + ltc_prev_cycle = 0; + ltc_timecode_offset = 0; + ltc_timecode_negative_offset = false; + midi_control_ui = 0; + _punch_or_loop = NoConstraint; + current_usecs_per_track = 1000; + _tempo_map = 0; + _all_route_group = new RouteGroup (*this, "all"); + _adding_routes_in_progress = false; + _reconnecting_routes_in_progress = false; + _route_deletion_in_progress = false; + _track_number_decimals= 1; + default_fade_steepness = 0; + default_fade_msecs = 0; + _total_free_4k_blocks = 0; + _total_free_4k_blocks_uncertain = false; + no_questions_about_missing_files = false; + _playback_load = 0; + _capture_load = 0; + _bundle_xml_node = 0; + _current_trans = 0; + _clicking = false; + _click_rec_only = false; + click_data = 0; + click_emphasis_data = 0; + click_length = 0; + click_emphasis_length = 0; + _clicks_cleared = 0; + _count_in_samples = 0; + _play_range = false; + _range_selection = -1,-1; + _object_selection = -1,-1; + _preroll_record_trim_len = 0; + _count_in_once = false; + main_outs = 0; + first_file_data_format_reset = true; + first_file_header_format_reset = true; + have_looped = false; + _have_rec_enabled_track = false; + _have_rec_disabled_track = true; + _step_editors = 0; + _suspend_timecode_transmission = 0; + _speakers = new Speakers; + _ignore_route_processor_changes = 0; + _ignored_a_processor_change = 0; + midi_clock = 0; + _scene_changer = 0; + _midi_ports = 0; + _mmc = 0; + _vca_manager = new VCAManager (*this); + _selection = new CoreSelection (*this); + _global_locate_pending = false; + _had_destructive_tracks = false; +#endif +>>>>>>> libardour: conversion to use timeline types (mega-commit) + created_with = string_compose ("%1 %2", PROGRAM_NAME, revision); pthread_mutex_init (&_rt_emit_mutex, 0); @@ -843,7 +990,7 @@ Session::setup_click () { _clicking = false; - boost::shared_ptr gl (new AutomationList (Evoral::Parameter (GainAutomation))); + boost::shared_ptr gl (new AutomationList (Evoral::Parameter (GainAutomation), Temporal::AudioTime)); boost::shared_ptr gain_control = boost::shared_ptr (new GainControl (*this, Evoral::Parameter(GainAutomation), gl)); _click_io.reset (new ClickIO (*this, X_("Click"))); @@ -1400,7 +1547,7 @@ Session::set_track_monitor_input_status (bool yn) void Session::auto_punch_start_changed (Location* location) { - replace_event (SessionEvent::PunchIn, location->start()); + replace_event (SessionEvent::PunchIn, location->start_sample()); if (get_record_enabled() && config.get_punch_in() && !actively_recording ()) { /* capture start has been changed, so save new pending state */ @@ -1493,7 +1640,7 @@ Session::unset_punch () void Session::auto_punch_end_changed (Location* location) { - replace_event (SessionEvent::PunchOut, location->end()); + replace_event (SessionEvent::PunchOut, location->end_sample()); } void @@ -1510,13 +1657,13 @@ Session::auto_loop_changed (Location* location) return; } - replace_event (SessionEvent::AutoLoop, location->end(), location->start()); + replace_event (SessionEvent::AutoLoop, location->end_sample(), location->start_sample()); if (transport_rolling()) { if (get_play_loop ()) { - if (_transport_sample < location->start() || _transport_sample > location->end()) { + if (_transport_sample < location->start_sample() || _transport_sample > location->end_sample()) { /* new loop range excludes current transport * sample => relocate to beginning of loop and roll. @@ -1528,7 +1675,7 @@ Session::auto_loop_changed (Location* location) */ loop_changing = true; - request_locate (location->start(), MustRoll); + request_locate (location->start_sample(), MustRoll); } else { @@ -1551,13 +1698,13 @@ Session::auto_loop_changed (Location* location) samplepos_t pos; if (select_playhead_priority_target (pos)) { - if (pos == location->start()) { + if (pos == location->start_sample()) { request_locate (pos); } } } - last_loopend = location->end(); + last_loopend = location->end_sample(); set_dirty (); } @@ -1599,7 +1746,7 @@ Session::set_auto_punch_location (Location* location) } void -Session::set_session_extents (samplepos_t start, samplepos_t end) +Session::set_session_extents (timepos_t const & start, timepos_t const & end) { if (end <= start) { error << _("Session: you can't use that location for session start/end)") << endmsg; @@ -1608,7 +1755,7 @@ Session::set_session_extents (samplepos_t start, samplepos_t end) Location* existing; if ((existing = _locations->session_range_location()) == 0) { - _session_range_location = new Location (*this, start, end, _("session"), Location::IsSessionRange, 0); + _session_range_location = new Location (*this, start, end, _("session"), Location::IsSessionRange); _locations->add (_session_range_location); } else { existing->set( start, end ); @@ -1625,7 +1772,7 @@ Session::set_auto_loop_location (Location* location) if ((existing = _locations->auto_loop_location()) != 0 && existing != location) { loop_connections.drop_connections (); existing->set_auto_loop (false, this); - remove_event (existing->end(), SessionEvent::AutoLoop); + remove_event (existing->end_sample(), SessionEvent::AutoLoop); auto_loop_location_changed (0); } @@ -1640,7 +1787,7 @@ Session::set_auto_loop_location (Location* location) return; } - last_loopend = location->end(); + last_loopend = location->end_sample(); loop_connections.drop_connections (); @@ -1709,11 +1856,11 @@ Session::consolidate_skips (Location* loc) continue; } - switch (Evoral::coverage ((*l)->start(), (*l)->end(), loc->start(), loc->end())) { - case Evoral::OverlapInternal: - case Evoral::OverlapExternal: - case Evoral::OverlapStart: - case Evoral::OverlapEnd: + switch (Temporal::coverage_exclusive_ends ((*l)->start(), (*l)->end(), loc->start(), loc->end())) { + case Temporal::OverlapInternal: + case Temporal::OverlapExternal: + case Temporal::OverlapStart: + case Temporal::OverlapEnd: /* adjust new location to cover existing one */ loc->set_start (min (loc->start(), (*l)->start())); loc->set_end (max (loc->end(), (*l)->end())); @@ -1723,7 +1870,7 @@ Session::consolidate_skips (Location* loc) l = all_locations.erase (l); break; - case Evoral::OverlapNone: + case Temporal::OverlapNone: ++l; break; } @@ -1751,7 +1898,7 @@ Session::_sync_locations_to_skips () Location* location = *i; if (location->is_skip() && location->is_skipping()) { - SessionEvent* ev = new SessionEvent (SessionEvent::Skip, SessionEvent::Add, location->start(), location->end(), 1.0); + SessionEvent* ev = new SessionEvent (SessionEvent::Skip, SessionEvent::Add, location->start_sample(), location->end_sample(), 1.0); queue_event (ev); } } @@ -1783,7 +1930,8 @@ Session::location_added (Location *location) location->EndChanged.connect_same_thread (skip_update_connections, boost::bind (&Session::update_marks, this, location)); location->Changed.connect_same_thread (skip_update_connections, boost::bind (&Session::update_marks, this, location)); location->FlagsChanged.connect_same_thread (skip_update_connections, boost::bind (&Session::update_marks, this, location)); - location->PositionLockStyleChanged.connect_same_thread (skip_update_connections, boost::bind (&Session::update_marks, this, location)); +#warning NUTEMPO can locations have their lock style changed and how + // location->PositionLockStyleChanged.connect_same_thread (skip_update_connections, boost::bind (&Session::update_marks, this, location)); } if (location->is_range_marker()) { @@ -1793,7 +1941,8 @@ Session::location_added (Location *location) location->EndChanged.connect_same_thread (skip_update_connections, boost::bind (&Session::update_marks, this, location)); location->Changed.connect_same_thread (skip_update_connections, boost::bind (&Session::update_marks, this, location)); location->FlagsChanged.connect_same_thread (skip_update_connections, boost::bind (&Session::update_marks, this, location)); - location->PositionLockStyleChanged.connect_same_thread (skip_update_connections, boost::bind (&Session::update_marks, this, location)); +#warning NUTEMPO can locations have their lock style changed and how + // location->PositionLockStyleChanged.connect_same_thread (skip_update_connections, boost::bind (&Session::update_marks, this, location)); } if (location->is_skip()) { @@ -1803,7 +1952,8 @@ Session::location_added (Location *location) location->EndChanged.connect_same_thread (skip_update_connections, boost::bind (&Session::update_skips, this, location, true)); location->Changed.connect_same_thread (skip_update_connections, boost::bind (&Session::update_skips, this, location, true)); location->FlagsChanged.connect_same_thread (skip_update_connections, boost::bind (&Session::update_skips, this, location, false)); - location->PositionLockStyleChanged.connect_same_thread (skip_update_connections, boost::bind (&Session::update_marks, this, location)); +#warning NUTEMPO can locations have their lock style changed and how + // location->PositionLockStyleChanged.connect_same_thread (skip_update_connections, boost::bind (&Session::update_marks, this, location)); update_skips (location, true); } @@ -4268,7 +4418,7 @@ Session::playlist_region_added (boost::weak_ptr w) /* If so, update the session range markers */ if (!in.empty ()) { - maybe_update_session_range (r->position (), r->last_sample ()); + maybe_update_session_range (r->nt_position (), r->nt_end ()); } } @@ -4276,7 +4426,7 @@ Session::playlist_region_added (boost::weak_ptr w) * b is after the current end. */ void -Session::maybe_update_session_range (samplepos_t a, samplepos_t b) +Session::maybe_update_session_range (timepos_t const & a, timepos_t const & b) { if (loading ()) { return; @@ -4286,7 +4436,7 @@ Session::maybe_update_session_range (samplepos_t a, samplepos_t b) if (_session_range_location == 0) { - set_session_extents (a, b + session_end_marker_shift_samples); + set_session_extents (a, b + timepos_t (session_end_marker_shift_samples)); } else { @@ -4307,18 +4457,18 @@ Session::set_session_range_is_free (bool yn) } void -Session::playlist_ranges_moved (list > const & ranges) +Session::playlist_ranges_moved (list const & ranges) { - for (list >::const_iterator i = ranges.begin(); i != ranges.end(); ++i) { - maybe_update_session_range (i->to, i->to + i->length); + for (list::const_iterator i = ranges.begin(); i != ranges.end(); ++i) { + maybe_update_session_range (i->from, i->to); } } void -Session::playlist_regions_extended (list > const & ranges) +Session::playlist_regions_extended (list const & ranges) { - for (list >::const_iterator i = ranges.begin(); i != ranges.end(); ++i) { - maybe_update_session_range (i->from, i->to); + for (list::const_iterator i = ranges.begin(); i != ranges.end(); ++i) { + maybe_update_session_range (i->start(), i->end()); } } @@ -5409,9 +5559,10 @@ Session::tempo_map_changed (const PropertyChange&) void Session::update_locations_after_tempo_map_change (const Locations::LocationList& loc) { - for (Locations::LocationList::const_iterator i = loc.begin(); i != loc.end(); ++i) { - (*i)->recompute_samples_from_beat (); - } +#warning NUTEMPO this is probably unnecessary now + // for (Locations::LocationList::const_iterator i = loc.begin(); i != loc.end(); ++i) { + // (*i)->recompute_samples_from_beat (); + // } } /** Ensures that all buffers (scratch, send, silent, etc) are allocated for @@ -5862,13 +6013,35 @@ Session::write_one_track (Track& track, samplepos_t start, samplepos_t end, /* MidiTrack::export_stuff moves event to the current cycle */ ev.set_time(ev.time() + out_pos - position); } - (*m)->src->append_event_samples ((*m)->lock, ev, (*m)->src->natural_position()); + (*m)->src->append_event_samples ((*m)->lock, ev, (*m)->src->natural_position().samples()); } } out_pos += current_chunk; latency_skip = 0; } + tracker.resolve_notes (resolved, end-1); + + if (!resolved.empty()) { + + for (vector::iterator m = midi_source_locks.begin(); m != midi_source_locks.end(); ++m) { + + for (MidiBuffer::iterator i = resolved.begin(); i != resolved.end(); ++i) { + Evoral::Event ev = *i; + if (!endpoint || for_export) { + ev.set_time(ev.time() - position); + } + (*m)->src->append_event_samples ((*m)->lock, ev, (*m)->src->natural_position().samples()); + } + } + } + + for (vector::iterator m = midi_source_locks.begin(); m != midi_source_locks.end(); ++m) { + delete *m; + } + + midi_source_locks.clear (); + /* post-roll, pick up delayed processor output */ latency_skip = track.bounce_get_latency (endpoint, include_endpoint, for_export, for_freeze); @@ -6282,7 +6455,7 @@ Session::get_tracks () const } boost::shared_ptr -Session::get_routes_with_regions_at (samplepos_t const p) const +Session::get_routes_with_regions_at (timepos_t const & p) const { boost::shared_ptr r = routes.reader (); boost::shared_ptr rl (new RouteList); @@ -6310,7 +6483,7 @@ void Session::goto_end () { if (_session_range_location) { - request_locate (_session_range_location->end(), MustStop); + request_locate (_session_range_location->end().samples(), MustStop); } else { request_locate (0, MustStop); } @@ -6320,7 +6493,7 @@ void Session::goto_start (bool and_roll) { if (_session_range_location) { - request_locate (_session_range_location->start(), and_roll ? MustRoll : RollIfAppropriate); + request_locate (_session_range_location->start().samples(), and_roll ? MustRoll : RollIfAppropriate); } else { request_locate (0, and_roll ? MustRoll : RollIfAppropriate); } @@ -6329,13 +6502,13 @@ Session::goto_start (bool and_roll) samplepos_t Session::current_start_sample () const { - return _session_range_location ? _session_range_location->start() : 0; + return _session_range_location ? _session_range_location->start().samples() : 0; } samplepos_t Session::current_end_sample () const { - return _session_range_location ? _session_range_location->end() : 0; + return _session_range_location ? _session_range_location->end().samples() : 0; } void @@ -6926,25 +7099,25 @@ Session::reconnect_ltc_output () void Session::set_range_selection (samplepos_t start, samplepos_t end) { - _range_selection = Evoral::Range (start, end); + _range_selection = Temporal::Range (timepos_t (start), timepos_t (end)); } void Session::set_object_selection (samplepos_t start, samplepos_t end) { - _object_selection = Evoral::Range (start, end); + _object_selection = Temporal::Range (timepos_t (start), timepos_t (end)); } void Session::clear_range_selection () { - _range_selection = Evoral::Range (-1,-1); + _range_selection = Temporal::Range (timepos_t::max (Temporal::AudioTime), timepos_t::max (Temporal::AudioTime)); } void Session::clear_object_selection () { - _object_selection = Evoral::Range (-1,-1); + _object_selection = Temporal::Range (timepos_t::max (Temporal::AudioTime), timepos_t::max (Temporal::AudioTime)); } void diff --git a/libs/ardour/session_click.cc b/libs/ardour/session_click.cc index 4b890979a0..a474c87175 100644 --- a/libs/ardour/session_click.cc +++ b/libs/ardour/session_click.cc @@ -104,8 +104,8 @@ Session::click (samplepos_t cycle_start, samplecnt_t nframes) Location* loop_location = get_play_loop () ? locations()->auto_loop_location () : NULL; if (loop_location) { - const samplepos_t loop_start = loop_location->start (); - const samplepos_t loop_end = loop_location->end (); + const samplepos_t loop_start = loop_location->start_sample(); + const samplepos_t loop_end = loop_location->end_sample(); if (start >= loop_end) { samplecnt_t off = (start - loop_end) % (loop_end - loop_start); start = loop_start + off; @@ -180,8 +180,8 @@ Session::run_click (samplepos_t start, samplepos_t nframes) bool crossloop = false; samplecnt_t span = nframes; if (loop_location) { - const samplepos_t loop_start = loop_location->start (); - const samplepos_t loop_end = loop_location->end (); + const samplepos_t loop_start = loop_location->start_sample (); + const samplepos_t loop_end = loop_location->end_sample (); if (start >= loop_end) { samplecnt_t off = (start - loop_end) % (loop_end - loop_start); start = loop_start + off; @@ -197,8 +197,8 @@ Session::run_click (samplepos_t start, samplepos_t nframes) Click *clk = *i; if (loop_location) { - const samplepos_t loop_start = loop_location->start (); - const samplepos_t loop_end = loop_location->end (); + const samplepos_t loop_start = loop_location->start_sample (); + const samplepos_t loop_end = loop_location->end_sample (); /* remove any clicks that are outside loop location, and not currently playing */ if ((clk->start < loop_start || clk->start >= loop_end) && clk->offset == 0) { delete clk; @@ -217,7 +217,7 @@ Session::run_click (samplepos_t start, samplepos_t nframes) } else if (crossloop) { /* When loop wraps around in current cycle, take * clicks at loop-start into account */ - const samplepos_t loop_start = loop_location->start (); + const samplepos_t loop_start = loop_location->start_sample (); internal_offset = clk->start - loop_start + span; } else if (_count_in_samples > 0) { ++i; diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index ade58170ad..6c36ce6adc 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -1455,8 +1455,8 @@ Session::state (bool save_template, snapshot_t snapshot_type, bool only_used_ass const bool was_dirty = dirty(); // for a template, just create a new Locations, populate it // with the default start and end, and get the state for that. - Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange, 0); - range->set (max_samplepos, 0); + Location* range = new Location (*this, timepos_t (Temporal::AudioTime), timepos_t (Temporal::AudioTime), _("session"), Location::IsSessionRange); + range->set (timepos_t::max (Temporal::AudioTime), timepos_t (Temporal::AudioTime)); loc.add (range); XMLNode& locations_state = loc.get_state(); @@ -1674,7 +1674,7 @@ Session::set_state (const XMLNode& node, int version) locations_changed (); if (_session_range_location) { - AudioFileSource::set_header_position_offset (_session_range_location->start()); + AudioFileSource::set_header_position_offset (_session_range_location->start().samples()); } if ((child = find_named_node (node, "Regions")) == 0) { @@ -2327,7 +2327,7 @@ Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/) for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) { boost::shared_ptr sfp = boost::dynamic_pointer_cast (*sx); if (sfp) { - sfp->set_length (region->length()); + sfp->set_length (region->nt_length().samples()); } } } @@ -2396,7 +2396,7 @@ Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/) for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) { boost::shared_ptr sfp = boost::dynamic_pointer_cast (*sx); if (sfp) { - sfp->set_length (region->length()); + sfp->set_length (region->nt_length().samples()); } } } @@ -3518,7 +3518,7 @@ Session::cleanup_sources (CleanupReport& rep) * capture files. */ - if (!i->second->used() && (i->second->length(i->second->natural_position()) > 0)) { + if (!i->second->used() && (i->second->empty())) { dead_sources.push_back (i->second); } @@ -5452,7 +5452,7 @@ Session::archive_session (const std::string& dest, continue; } boost::shared_ptr afs = boost::dynamic_pointer_cast (i->second); - if (!afs || afs->readable_length () == 0) { + if (!afs || afs->length ().zero()) { continue; } if (only_used_sources) { @@ -5471,7 +5471,7 @@ Session::archive_session (const std::string& dest, continue; } boost::shared_ptr afs = boost::dynamic_pointer_cast (i->second); - if (!afs || afs->readable_length () == 0) { + if (!afs || afs->length ().zero()) { continue; } @@ -5487,7 +5487,7 @@ Session::archive_session (const std::string& dest, std::string from = afs->path(); if (compress_audio != NO_ENCODE) { - total_size += afs->readable_length (); + total_size += afs->readable_length_samples (); } else { /* copy files as-is */ if (!afs->within_session()) { @@ -5535,7 +5535,7 @@ Session::archive_session (const std::string& dest, continue; } boost::shared_ptr afs = boost::dynamic_pointer_cast (i->second); - if (!afs || afs->readable_length () == 0) { + if (!afs || afs->length ().zero()) { continue; } @@ -5570,7 +5570,7 @@ Session::archive_session (const std::string& dest, } if (progress) { - progress->descend ((float)afs->readable_length () / total_size); + progress->descend ((float)afs->readable_length_samples () / total_size); } try { diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc index 15ef5e83a2..59f59fa04d 100644 --- a/libs/ardour/session_transport.cc +++ b/libs/ardour/session_transport.cc @@ -242,7 +242,7 @@ Session::locate (samplepos_t target_sample, bool for_loop_end, bool force, bool Location* al = _locations->auto_loop_location(); if (al) { - if (_transport_sample < al->start() || _transport_sample >= al->end()) { + if (_transport_sample < al->start_sample() || _transport_sample >= al->end_sample()) { // located outside the loop: cancel looping directly, this is called from event handling context @@ -258,7 +258,7 @@ Session::locate (samplepos_t target_sample, bool for_loop_end, bool force, bool set_track_loop (false); } - } else if (_transport_sample == al->start()) { + } else if (_transport_sample == al->start_sample()) { // located to start of loop - this is looping, basically @@ -415,7 +415,6 @@ Session::set_transport_speed (double speed) * The 0.2% dead-zone is somewhat arbitrary. Main use-case * for TransportStateChange() here is the ShuttleControl display. */ - const double act_speed = actual_speed (); if (fabs (_signalled_varispeed - act_speed) > .002 @@ -1012,7 +1011,7 @@ Session::request_play_loop (bool yn, bool change_transport_roll) } void -Session::request_play_range (list* range, bool leave_rolling) +Session::request_play_range (list* range, bool leave_rolling) { SessionEvent* ev = new SessionEvent (SessionEvent::SetPlayAudioRange, SessionEvent::Add, SessionEvent::Immediate, 0, (leave_rolling ? _transport_fsm->default_speed() : 0.0)); if (range) { @@ -1202,13 +1201,13 @@ Session::non_realtime_locate () Location *loc = _locations->auto_loop_location(); - if (!loc || (_transport_sample < loc->start() || _transport_sample >= loc->end())) { + if (!loc || (_transport_sample < loc->start().samples() || _transport_sample >= loc->end().samples())) { /* jumped out of loop range: stop tracks from looping, but leave loop (mode) enabled. */ set_track_loop (false); - } else if (loc && ((loc->start() <= _transport_sample) || (loc->end() > _transport_sample))) { + } else if (loc && ((loc->start().samples() <= _transport_sample) || (loc->end().samples() > _transport_sample))) { /* jumping to start of loop. This might have been done before but it is * idempotent and cheap. Doing it here ensures that when we start playback @@ -1576,7 +1575,7 @@ Session::set_play_loop (bool yn, bool change_transport_state) /* set all tracks to use internal looping */ set_track_loop (true); - merge_event (new SessionEvent (SessionEvent::AutoLoop, SessionEvent::Replace, loc->end(), loc->start(), 0.0f)); + merge_event (new SessionEvent (SessionEvent::AutoLoop, SessionEvent::Replace, loc->end().samples(), loc->start().samples(), 0.0f)); if (!Config->get_loop_is_mode()) { if (transport_rolling()) { @@ -1584,11 +1583,11 @@ Session::set_play_loop (bool yn, bool change_transport_state) loop_changing = true; } /* args: position, disposition, for_loop_end=false, force=true */ - TFSM_LOCATE (loc->start(), MustRoll, false, true); + TFSM_LOCATE (loc->start().samples(), MustRoll, false, true); } else { if (!transport_rolling()) { /* loop-is-mode: not rolling, just locate to loop start */ - TFSM_LOCATE (loc->start(), MustStop, false, true); + TFSM_LOCATE (loc->start().samples(), MustStop, false, true); } } TransportStateChange (); /* EMIT SIGNAL */ @@ -1661,7 +1660,7 @@ Session::unset_play_range () } void -Session::set_play_range (list& range, bool leave_rolling) +Session::set_play_range (list& range, bool leave_rolling) { SessionEvent* ev; @@ -1685,12 +1684,12 @@ Session::set_play_range (list& range, bool leave_rolling) /* cancel loop play */ unset_play_loop (); - list::size_type sz = range.size(); + list::size_type sz = range.size(); if (sz > 1) { - list::iterator i = range.begin(); - list::iterator next; + list::iterator i = range.begin(); + list::iterator next; while (i != range.end()) { @@ -1700,7 +1699,7 @@ Session::set_play_range (list& range, bool leave_rolling) /* locating/stopping is subject to delays for declicking. */ - samplepos_t requested_sample = i->end; + samplepos_t requested_sample = i->end().samples(); if (requested_sample > current_block_size) { requested_sample -= current_block_size; @@ -1711,7 +1710,7 @@ Session::set_play_range (list& range, bool leave_rolling) if (next == range.end()) { ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, requested_sample, 0, 0.0f); } else { - ev = new SessionEvent (SessionEvent::RangeLocate, SessionEvent::Add, requested_sample, (*next).start, 0.0f); + ev = new SessionEvent (SessionEvent::RangeLocate, SessionEvent::Add, requested_sample, (*next).start().samples(), 0.0f); } merge_event (ev); @@ -1721,7 +1720,7 @@ Session::set_play_range (list& range, bool leave_rolling) } else if (sz == 1) { - ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, range.front().end, 0, 0.0f); + ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, range.front().end().samples(), 0, 0.0f); merge_event (ev); } @@ -1732,7 +1731,7 @@ Session::set_play_range (list& range, bool leave_rolling) /* now start rolling at the right place */ - ev = new SessionEvent (SessionEvent::LocateRoll, SessionEvent::Add, SessionEvent::Immediate, range.front().start, 0.0f, false); + ev = new SessionEvent (SessionEvent::LocateRoll, SessionEvent::Add, SessionEvent::Immediate, range.front().start().samples(), 0.0f, false); merge_event (ev); DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC5 with speed = %1\n", _transport_fsm->transport_speed())); @@ -1742,8 +1741,8 @@ Session::set_play_range (list& range, bool leave_rolling) void Session::request_bounded_roll (samplepos_t start, samplepos_t end) { - AudioRange ar (start, end, 0); - list lar; + TimelineRange ar (timepos_t (start), timepos_t (end), 0); + list lar; lar.push_back (ar); request_play_range (&lar, true); diff --git a/libs/ardour/session_vst.cc b/libs/ardour/session_vst.cc index dd1ca0164a..d300b977d3 100644 --- a/libs/ardour/session_vst.cc +++ b/libs/ardour/session_vst.cc @@ -268,10 +268,10 @@ intptr_t Session::vst_callback ( newflags |= kVstTransportCycleActive; Location * looploc = session->locations ()->auto_loop_location (); if (looploc) try { - timeinfo->cycleStartPos = session->tempo_map ().quarter_note_at_sample_rt (looploc->start ()); - timeinfo->cycleEndPos = session->tempo_map ().quarter_note_at_sample_rt (looploc->end ()); - - newflags |= kVstCyclePosValid; +#warning NUTEMPO FIXME needs new session tempo map + //timeinfo->cycleStartPos = session->tempo_map ().quarter_note_at_sample_rt (looploc->start ()); + //timeinfo->cycleEndPos = session->tempo_map ().quarter_note_at_sample_rt (looploc->end ()); + // newflags |= kVstCyclePosValid; } catch (...) { } } @@ -519,7 +519,7 @@ intptr_t Session::vst_callback ( if (plug && plug->plugin_insert ()) { boost::shared_ptr ac = plug->plugin_insert ()->automation_control (Evoral::Parameter (PluginAutomation, 0, index)); if (ac) { - ac->start_touch (ac->session().transport_sample()); + ac->start_touch (timepos_t (ac->session().transport_sample())); } } return 0; @@ -530,7 +530,7 @@ intptr_t Session::vst_callback ( if (plug && plug->plugin_insert ()) { boost::shared_ptr ac = plug->plugin_insert ()->automation_control (Evoral::Parameter (PluginAutomation, 0, index)); if (ac) { - ac->stop_touch (ac->session().transport_sample()); + ac->stop_touch (timepos_t (ac->session().transport_sample())); } } return 0; diff --git a/libs/ardour/slavable_automation_control.cc b/libs/ardour/slavable_automation_control.cc index 505c8ebfc2..c875aec0ca 100644 --- a/libs/ardour/slavable_automation_control.cc +++ b/libs/ardour/slavable_automation_control.cc @@ -86,7 +86,7 @@ SlavableAutomationControl::get_value_locked() const /* read or write masters lock must be held */ if (_masters.empty()) { - return Control::get_double (false, _session.transport_sample()); + return Control::get_double (false, timepos_t (_session.transport_sample())); } if (_desc.toggled) { @@ -94,12 +94,12 @@ SlavableAutomationControl::get_value_locked() const * enabled, this slave is enabled. So check our own value * first, because if we are enabled, we can return immediately. */ - if (Control::get_double (false, _session.transport_sample())) { + if (Control::get_double (false, timepos_t (_session.transport_sample()))) { return _desc.upper; } } - return Control::get_double() * get_masters_value_locked (); + return Control::get_double () * get_masters_value_locked (); } /** Get the current effective `user' value based on automation state */ @@ -116,7 +116,7 @@ SlavableAutomationControl::get_value() const } return get_value_locked (); } else { - return Control::get_double (true, _session.transport_sample()) * get_masters_value_locked(); + return Control::get_double (true, timepos_t (_session.transport_sample())) * get_masters_value_locked(); } } @@ -133,7 +133,7 @@ SlavableAutomationControl::get_masters_curve_locked (samplepos_t, samplepos_t, f } bool -SlavableAutomationControl::masters_curve_multiply (samplepos_t start, samplepos_t end, float* vec, samplecnt_t veclen) const +SlavableAutomationControl::masters_curve_multiply (timepos_t const & start, timepos_t const & end, float* vec, samplecnt_t veclen) const { gain_t* scratch = _session.scratch_automation_buffer (); bool from_list = _list && boost::dynamic_pointer_cast(_list)->automation_playback(); @@ -368,7 +368,8 @@ SlavableAutomationControl::remove_master (boost::shared_ptr m double new_val = old_val * master_ratio; if (old_val != new_val) { - AutomationControl::set_double (new_val, Controllable::NoGroup); + timepos_t foo; + AutomationControl::set_double (new_val, foo, Controllable::NoGroup); } /* ..and update automation */ @@ -441,7 +442,8 @@ SlavableAutomationControl::clear_masters () double new_val = old_val * master_ratio; if (old_val != new_val) { - AutomationControl::set_double (new_val, Controllable::NoGroup); + timepos_t foo; + AutomationControl::set_double (new_val, foo, Controllable::NoGroup); } /* ..and update automation */ @@ -471,7 +473,7 @@ SlavableAutomationControl::clear_masters () } bool -SlavableAutomationControl::find_next_event_locked (double now, double end, Evoral::ControlEvent& next_event) const +SlavableAutomationControl::find_next_event_locked (timepos_t const & now, timepos_t const & end, Evoral::ControlEvent& next_event) const { if (_masters.empty()) { return false; @@ -537,7 +539,7 @@ SlavableAutomationControl::automation_run (samplepos_t start, pframes_t nframes) assert (_list); bool valid = false; - double val = _list->rt_safe_eval (start, valid); + double val = _list->rt_safe_eval (timepos_t (start), valid); if (!valid) { return; } @@ -571,7 +573,7 @@ SlavableAutomationControl::boolean_automation_run_locked (samplepos_t start, pfr } boost::shared_ptr alist (ac->list()); bool valid = false; - const bool yn = alist->rt_safe_eval (start, valid) >= 0.5; + const bool yn = alist->rt_safe_eval (timepos_t (start), valid) >= 0.5; if (!valid) { continue; } diff --git a/libs/ardour/smf_source.cc b/libs/ardour/smf_source.cc index a5f4b8b7d9..784885870a 100644 --- a/libs/ardour/smf_source.cc +++ b/libs/ardour/smf_source.cc @@ -43,6 +43,8 @@ #include "evoral/Control.h" #include "evoral/SMF.h" +#include "temporal/tempo.h" + #include "ardour/debug.h" #include "ardour/midi_channel_filter.h" #include "ardour/midi_model.h" @@ -68,8 +70,6 @@ SMFSource::SMFSource (Session& s, const string& path, Source::Flag flags) , Evoral::SMF() , _open (false) , _last_ev_time_samples(0) - , _smf_last_read_end (0) - , _smf_last_read_time (0) { /* note that origin remains empty */ @@ -103,8 +103,6 @@ SMFSource::SMFSource (Session& s, const string& path) , Evoral::SMF() , _open (false) , _last_ev_time_samples(0) - , _smf_last_read_end (0) - , _smf_last_read_time (0) { /* note that origin remains empty */ @@ -134,8 +132,6 @@ SMFSource::SMFSource (Session& s, const XMLNode& node, bool must_exist) , FileSource(s, node, must_exist) , _open (false) , _last_ev_time_samples(0) - , _smf_last_read_end (0) - , _smf_last_read_time (0) { if (set_state(node, Stateful::loading_state_version)) { throw failed_constructor (); @@ -216,23 +212,22 @@ SMFSource::close () extern PBD::Timing minsert; -/** All stamps in audio samples */ -samplecnt_t -SMFSource::read_unlocked (const Lock& lock, +timecnt_t +SMFSource::read_unlocked (const Lock& lock, Evoral::EventSink& destination, - samplepos_t const source_start, - samplepos_t start, - samplecnt_t duration, - Evoral::Range* loop_range, - MidiStateTracker* tracker, - MidiChannelFilter* filter) const + timepos_t const & source_start, + timecnt_t const & start, + timecnt_t const & duration, + Temporal::Range* loop_range, + MidiStateTracker* tracker, + MidiChannelFilter* filter) const { int ret = 0; - uint64_t time = 0; // in SMF ticks, 1 tick per _ppqn + timepos_t time; // in SMF ticks, 1 tick per _ppqn if (writable() && !_open) { /* nothing to read since nothing has ben written */ - return duration; + return timecnt_t(); } DEBUG_TRACE (DEBUG::MidiSourceIO, string_compose ("SMF read_unlocked: start %1 duration %2\n", start, duration)); @@ -244,9 +239,9 @@ SMFSource::read_unlocked (const Lock& lock, size_t scratch_size = 0; // keep track of scratch to minimize reallocs - BeatsSamplesConverter converter(_session.tempo_map(), source_start); + /* start of read in SMF ticks (which may differ from our own musical ticks */ + const uint64_t start_ticks = llrint (start.beats().to_ticks() * (Temporal::Beats::PPQN / ppqn())); - const uint64_t start_ticks = converter.from(start).to_ticks(); DEBUG_TRACE (DEBUG::MidiSourceIO, string_compose ("SMF read_unlocked: start in ticks %1\n", start_ticks)); if (_smf_last_read_end == 0 || start != _smf_last_read_end) { @@ -258,7 +253,7 @@ SMFSource::read_unlocked (const Lock& lock, ret = read_event(&ev_delta_t, &ev_size, &ev_buffer, &ignored); if (ret == -1) { // EOF _smf_last_read_end = start + duration; - return duration; + return timecnt_t(); } time += ev_delta_t; // accumulate delta time } @@ -292,15 +287,17 @@ SMFSource::read_unlocked (const Lock& lock, /* Note that we add on the source start time (in session samples) here so that ev_sample_time is in session samples. */ - const samplepos_t ev_sample_time = converter.to(Temporal::Beats::ticks_at_rate(time, ppqn())) + source_start; +#warning NUTEMPO FIXME needs session to use Temporal:;TempoMap + const samplepos_t ev_sample_time = 0; // = _session.tempo_map().sample_at (Temporal::Beats::ticks (time) + source_start.beats()); /* convert from Beats to samples */ + timepos_t est (ev_sample_time); if (loop_range) { - loop_range->squish (ev_sample_time); + est = loop_range->squish (est); } - if (ev_sample_time < start + duration) { + if (est < start + duration) { if (!filter || !filter->filter(ev_buffer, ev_size)) { - destination.write (ev_sample_time, Evoral::MIDI_EVENT, ev_size, ev_buffer); + destination.write (est.samples(), Evoral::MIDI_EVENT, ev_size, ev_buffer); if (tracker) { tracker->track(ev_buffer); } @@ -318,17 +315,20 @@ SMFSource::read_unlocked (const Lock& lock, return duration; } -samplecnt_t -SMFSource::write_unlocked (const Lock& lock, +timecnt_t +SMFSource::write_unlocked (const Lock& lock, MidiRingBuffer& source, - samplepos_t position, - samplecnt_t cnt) + timepos_t const & position, + timecnt_t const & cnt) { + if (!_writing) { mark_streaming_write_started (lock); } samplepos_t time; + const samplepos_t pos_samples = position.samples(); + const samplecnt_t cnt_samples = cnt.samples(); Evoral::EventType type; uint32_t size; @@ -348,8 +348,8 @@ SMFSource::write_unlocked (const Lock& lock, break; } - if ((cnt != max_samplecnt) && - (time > position + _capture_length + cnt)) { + if ((cnt != std::numeric_limits::max()) && + (time > pos_samples + _capture_length + cnt_samples)) { /* The diskstream doesn't want us to write everything, and this event is past the end of this block, so we're done for now. */ break; @@ -375,11 +375,11 @@ SMFSource::write_unlocked (const Lock& lock, } /* Convert event time from absolute to source relative. */ - if (time < position) { + if (time < pos_samples) { error << _("Event time is before MIDI source position") << endmsg; break; } - time -= position; + time -= pos_samples; ev.set(buf, size, time); ev.set_event_type(Evoral::MIDI_EVENT); @@ -389,7 +389,7 @@ SMFSource::write_unlocked (const Lock& lock, continue; } - append_event_samples(lock, ev, position); + append_event_samples(lock, ev, pos_samples); } Evoral::SMF::flush (); @@ -475,8 +475,10 @@ SMFSource::append_event_samples (const Glib::Threads::Mutex::Lock& lock, return; } - BeatsSamplesConverter converter(_session.tempo_map(), position); - const Temporal::Beats ev_time_beats = converter.from(ev.time()); +#warning NUTEMPO FIXME needs session to use new tempo map + // BeatsSamplesConverter converter(_session.tempo_map(), position); + //const Temporal::Beats ev_time_beats = converter.from(ev.time()); + const Temporal::Beats ev_time_beats; Evoral::event_id_t event_id; if (ev.id() < 0) { @@ -487,15 +489,17 @@ SMFSource::append_event_samples (const Glib::Threads::Mutex::Lock& lock, if (_model) { const Evoral::Event beat_ev (ev.event_type(), - ev_time_beats, - ev.size(), - const_cast(ev.buffer())); + ev_time_beats, + ev.size(), + const_cast(ev.buffer())); _model->append (beat_ev, event_id); } _length_beats = max(_length_beats, ev_time_beats); - const Temporal::Beats last_time_beats = converter.from (_last_ev_time_samples); +#warning NUTEMPO FIXME needs session to use new tempo map + //const Temporal::Beats last_time_beats = converter.from (_last_ev_time_samples); + const Temporal::Beats last_time_beats; const Temporal::Beats delta_time_beats = ev_time_beats - last_time_beats; const uint32_t delta_time_ticks = delta_time_beats.to_ticks(ppqn()); diff --git a/libs/ardour/sndfilesource.cc b/libs/ardour/sndfilesource.cc index f68f656e57..fb5d2e541f 100644 --- a/libs/ardour/sndfilesource.cc +++ b/libs/ardour/sndfilesource.cc @@ -228,7 +228,7 @@ SndFileSource::SndFileSource (Session& s, const AudioFileSource& other, const st , _sndfile (0) , _broadcast_info (0) { - if (other.readable_length () == 0) { + if (other.readable_length_samples () == 0) { throw failed_constructor(); } @@ -287,7 +287,7 @@ SndFileSource::SndFileSource (Session& s, const AudioFileSource& other, const st off += len; len = other.read (buf, off, 8192, other.channel ()); if (progress) { - progress->set_progress (0.5f * (float) off / other.readable_length ()); + progress->set_progress (0.5f * (float) off / other.readable_length_samples ()); } } @@ -309,7 +309,7 @@ SndFileSource::SndFileSource (Session& s, const AudioFileSource& other, const st off += len; len = other.read (buf, off, 8192, other.channel ()); if (progress) { - progress->set_progress (0.5f + 0.5f * (float) off / other.readable_length ()); + progress->set_progress (0.5f + 0.5f * (float) off / other.readable_length_samples ()); } } } @@ -423,12 +423,12 @@ SndFileSource::open () /* newly created files will not have a BWF header at this point in time. * Import will have called Source::set_natural_position() if one exists * in the original. */ - header_position_offset = _natural_position; + header_position_offset = _natural_position.samples(); } /* If a BWF header exists, set our _natural_position from it */ if (bwf_info_exists) { - set_natural_position (_broadcast_info->get_time_reference()); + set_natural_position (timepos_t (_broadcast_info->get_time_reference())); } if (_length != 0 && !bwf_info_exists) { @@ -504,17 +504,17 @@ SndFileSource::read_unlocked (Sample *dst, samplepos_t start, samplecnt_t cnt) c return 0; } - if (start > _length) { + if (start > _length.samples()) { /* read starts beyond end of data, just memset to zero */ file_cnt = 0; - } else if (start + cnt > _length) { + } else if (start + cnt > _length.samples()) { /* read ends beyond end of data, read some, memset the rest */ - file_cnt = _length - start; + file_cnt = _length.samples() - start; } else { @@ -604,13 +604,13 @@ SndFileSource::nondestructive_write_unlocked (Sample *data, samplecnt_t cnt) return 0; } - samplepos_t sample_pos = _length; + samplepos_t sample_pos = _length.samples(); if (write_float (data, sample_pos, cnt) != cnt) { return 0; } - update_length (_length + cnt); + update_length (_length + timecnt_t (cnt, timepos_t (Temporal::AudioTime))); if (_build_peakfiles) { compute_and_write_peaks (data, sample_pos, cnt, true, true); @@ -622,7 +622,7 @@ SndFileSource::nondestructive_write_unlocked (Sample *data, samplecnt_t cnt) int SndFileSource::update_header (samplepos_t when, struct tm& now, time_t tnow) { - set_natural_position (when); + set_natural_position (timepos_t (when)); if (_flags & Broadcast) { if (setup_broadcast_info (when, now, tnow)) { @@ -703,7 +703,7 @@ SndFileSource::set_header_natural_position () } assert (_broadcast_info); - _broadcast_info->set_time_reference (_natural_position); + _broadcast_info->set_time_reference (_natural_position.samples()); if (_sndfile == 0 || !_broadcast_info->write_to_file (_sndfile)) { error << string_compose (_("cannot set broadcast info for audio file %1 (%2); dropping broadcast info for this file"), @@ -736,7 +736,7 @@ SndFileSource::write_float (Sample* data, samplepos_t sample_pos, samplecnt_t cn } void -SndFileSource::set_natural_position (samplepos_t pos) +SndFileSource::set_natural_position (timepos_t const & pos) { AudioFileSource::set_natural_position (pos); } diff --git a/libs/ardour/solo_control.cc b/libs/ardour/solo_control.cc index 6497ac319e..88a2b884cc 100644 --- a/libs/ardour/solo_control.cc +++ b/libs/ardour/solo_control.cc @@ -28,9 +28,10 @@ using namespace ARDOUR; using namespace std; using namespace PBD; +#warning NUTEMPO QUESTION what time domain shoudl this really use? SoloControl::SoloControl (Session& session, std::string const & name, Soloable& s, Muteable& m) : SlavableAutomationControl (session, SoloAutomation, ParameterDescriptor (SoloAutomation), - boost::shared_ptr(new AutomationList(Evoral::Parameter(SoloAutomation))), + boost::shared_ptr(new AutomationList(Evoral::Parameter(SoloAutomation), Temporal::AudioTime)), name) , _soloable (s) , _muteable (m) diff --git a/libs/ardour/solo_isolate_control.cc b/libs/ardour/solo_isolate_control.cc index 16f764cd86..c154c94aa4 100644 --- a/libs/ardour/solo_isolate_control.cc +++ b/libs/ardour/solo_isolate_control.cc @@ -28,9 +28,9 @@ using namespace ARDOUR; using namespace std; using namespace PBD; -SoloIsolateControl::SoloIsolateControl (Session& session, std::string const & name, Soloable& s) +SoloIsolateControl::SoloIsolateControl (Session& session, std::string const & name, Soloable& s, Muteable& m) : SlavableAutomationControl (session, SoloIsolateAutomation, ParameterDescriptor (SoloIsolateAutomation), - boost::shared_ptr(new AutomationList(Evoral::Parameter(SoloIsolateAutomation))), + boost::shared_ptr(new AutomationList(Evoral::Parameter(SoloIsolateAutomation), Temporal::AudioTime)), name) , _soloable (s) , _solo_isolated (false) diff --git a/libs/ardour/solo_safe_control.cc b/libs/ardour/solo_safe_control.cc index 33d64c65bb..4bd07488f8 100644 --- a/libs/ardour/solo_safe_control.cc +++ b/libs/ardour/solo_safe_control.cc @@ -28,9 +28,10 @@ using namespace ARDOUR; using namespace std; using namespace PBD; +#warning NUTEMPO QUESTION what time domain shoudl this really use? SoloSafeControl::SoloSafeControl (Session& session, std::string const & name) : SlavableAutomationControl (session, SoloSafeAutomation, ParameterDescriptor (SoloSafeAutomation), - boost::shared_ptr(new AutomationList(Evoral::Parameter(SoloSafeAutomation))), + boost::shared_ptr(new AutomationList(Evoral::Parameter(SoloSafeAutomation), Temporal::AudioTime)), name) , _solo_safe (false) { diff --git a/libs/ardour/source.cc b/libs/ardour/source.cc index 97ea4f65b0..f2e6c34064 100644 --- a/libs/ardour/source.cc +++ b/libs/ardour/source.cc @@ -394,10 +394,11 @@ Source::mark_for_remove () } void -Source::set_natural_position (samplepos_t pos) +Source::set_natural_position (timepos_t const & pos) { _natural_position = pos; _have_natural_position = true; + _length.set_position (pos); } void @@ -459,9 +460,9 @@ Source::add_cue_marker (CueMarker const & cm) } bool -Source::move_cue_marker (CueMarker const & cm, samplepos_t source_relative_position) +Source::move_cue_marker (CueMarker const & cm, timepos_t const & source_relative_position) { - if (source_relative_position > length (0)) { + if (source_relative_position > length ()) { return false; } @@ -507,3 +508,15 @@ Source::clear_cue_markers () CueMarkersChanged(); /* EMIT SIGNAL */ return true; } + +Source::empty () const +{ + return _length == timecnt_t(); +} + +timecnt_t +Source::length() const +{ + return _length; +} + diff --git a/libs/ardour/source_factory.cc b/libs/ardour/source_factory.cc index da6d2d0bfa..64df7aba62 100644 --- a/libs/ardour/source_factory.cc +++ b/libs/ardour/source_factory.cc @@ -33,7 +33,6 @@ #include "ardour/boost_debug.h" #include "ardour/ffmpegfilesource.h" #include "ardour/midi_playlist.h" -#include "ardour/midi_playlist_source.h" #include "ardour/mp3filesource.h" #include "ardour/source.h" #include "ardour/source_factory.h" @@ -389,7 +388,7 @@ SourceFactory::createForRecovery (DataType type, Session& s, const std::string& boost::shared_ptr SourceFactory::createFromPlaylist (DataType type, Session& s, boost::shared_ptr p, const PBD::ID& orig, const std::string& name, - uint32_t chn, sampleoffset_t start, samplecnt_t len, bool copy, bool defer_peaks) + uint32_t chn, timepos_t start, timepos_t const & len, bool copy, bool defer_peaks) { if (type == DataType::AUDIO) { try { @@ -400,7 +399,7 @@ SourceFactory::createFromPlaylist (DataType type, Session& s, boost::shared_ptr< if (copy) { ap.reset (new AudioPlaylist (ap, start, len, name, true)); - start = 0; + start = timecnt_t::zero_at (Temporal::AudioTime, timepos_t::zero (Temporal::AudioTime)); } Source* src = new AudioPlaylistSource (s, orig, name, ap, chn, start, len, Source::Flag (0)); @@ -422,29 +421,7 @@ SourceFactory::createFromPlaylist (DataType type, Session& s, boost::shared_ptr< } else if (type == DataType::MIDI) { - try { - - boost::shared_ptr ap = boost::dynamic_pointer_cast(p); - - if (ap) { - - if (copy) { - ap.reset (new MidiPlaylist (ap, start, len, name, true)); - start = 0; - } - - Source* src = new MidiPlaylistSource (s, orig, name, ap, chn, start, len, Source::Flag (0)); - boost::shared_ptr ret (src); - - SourceCreated (ret); - return ret; - } - } - - catch (failed_constructor& err) { - /* relax - return at function scope */ - } - + /* fail - not implemented, and probably too difficult to do */ } throw failed_constructor (); diff --git a/libs/ardour/srcfilesource.cc b/libs/ardour/srcfilesource.cc index ab7d3376d4..dfecf555e7 100644 --- a/libs/ardour/srcfilesource.cc +++ b/libs/ardour/srcfilesource.cc @@ -63,7 +63,7 @@ SrcFileSource::SrcFileSource (Session& s, boost::shared_ptr src } - _ratio = s.nominal_sample_rate() / _source->sample_rate(); + _ratio = s.nominal_sample_rate() / _source->sample_rate(); _src_data.src_ratio = _ratio; src_buffer_size = ceil((double)max_blocksize / _ratio) + 2; @@ -119,8 +119,7 @@ SrcFileSource::read_unlocked (Sample *dst, samplepos_t start, samplecnt_t cnt) c _src_data.input_frames = _source->read (_src_buffer, _source_position, scnt); - if ((samplecnt_t) _src_data.input_frames * _ratio <= cnt - && _source_position + scnt >= _source->length(0)) { + if ((samplecnt_t) _src_data.input_frames * _ratio <= cnt && _source_position + scnt >= _source->length().samples()) { _src_data.end_of_input = true; DEBUG_TRACE (DEBUG::AudioPlayback, "SRC: END OF INPUT\n"); } else { diff --git a/libs/ardour/strip_silence.cc b/libs/ardour/strip_silence.cc index a2e8f543c2..2f25b786b2 100644 --- a/libs/ardour/strip_silence.cc +++ b/libs/ardour/strip_silence.cc @@ -114,13 +114,12 @@ StripSilence::run (boost::shared_ptr r, Progress* progress) PBD::PropertyList plist; boost::shared_ptr copy; - plist.add (Properties::length, i->second - i->first); - plist.add (Properties::position, r->position_sample() + (i->first - r->start_sample())); + plist.add (Properties::length, timecnt_t (i->second - i->first)); + plist.add (Properties::position, timepos_t (r->position_sample() + (i->first - r->start_sample()))); -#warning NUTEMPO are these arguments samples or superclocks? - const timecnt_t offset (i->first - r->start_sample(), timepos_t (i->first)); - - copy = boost::dynamic_pointer_cast (RegionFactory::create (region, offset, plist)); + copy = boost::dynamic_pointer_cast ( + RegionFactory::create (region, timecnt_t (i->first - r->start_sample(), timepos_t::zero (false)), plist) + ); copy->set_name (RegionFactory::new_region_name (region->name ())); diff --git a/libs/ardour/track.cc b/libs/ardour/track.cc index 592afeedd4..4986965bff 100644 --- a/libs/ardour/track.cc +++ b/libs/ardour/track.cc @@ -939,14 +939,14 @@ Track::use_captured_midi_sources (SourceList& srcs, CaptureInfos const & capture plist.add (Properties::name, whole_file_region_name); plist.add (Properties::whole_file, true); plist.add (Properties::automatic, true); - plist.add (Properties::start, 0); - plist.add (Properties::length, total_capture); + plist.add (Properties::start, timecnt_t (Temporal::BeatTime)); + plist.add (Properties::length, timecnt_t (total_capture, timepos_t (Temporal::BeatTime))); plist.add (Properties::layer, 0); boost::shared_ptr rx (RegionFactory::create (srcs, plist)); midi_region = boost::dynamic_pointer_cast (rx); - midi_region->special_set_position (capture_info.front()->start); + midi_region->special_set_position (timepos_t (capture_info.front()->start)); } catch (failed_constructor& err) { @@ -963,8 +963,10 @@ Track::use_captured_midi_sources (SourceList& srcs, CaptureInfos const & capture initial_capture = capture_info.front()->start; } - BeatsSamplesConverter converter (_session.tempo_map(), capture_info.front()->start); const samplepos_t preroll_off = _session.preroll_record_trim_len (); +#warning NUTEMPO FIX needs session to use new tempo map + //const timepos_t cstart (_session.tempo_map().quarter_note_at (capture_info.front()->start)); + const timepos_t cstart; for (ci = capture_info.begin(); ci != capture_info.end(); ++ci) { @@ -983,16 +985,15 @@ Track::use_captured_midi_sources (SourceList& srcs, CaptureInfos const & capture /* start of this region is the offset between the start of its capture and the start of the whole pass */ samplecnt_t start_off = (*ci)->start - initial_capture + (*ci)->loop_offset; - plist.add (Properties::start, start_off); - plist.add (Properties::length, (*ci)->samples); - plist.add (Properties::length_beats, converter.from((*ci)->samples).to_double()); - plist.add (Properties::start_beats, converter.from(start_off).to_double()); +#warning NUTEMPO thinkme MIDI region with start & length in samples + plist.add (Properties::start, timecnt_t (start_off, timepos_t::zero (false))); + plist.add (Properties::length, timecnt_t ((*ci)->samples, timepos_t::zero (false))); plist.add (Properties::name, region_name); boost::shared_ptr rx (RegionFactory::create (srcs, plist)); midi_region = boost::dynamic_pointer_cast (rx); if (preroll_off > 0) { - midi_region->trim_front ((*ci)->start - initial_capture + preroll_off); + midi_region->trim_front (timepos_t ((*ci)->start - initial_capture + preroll_off)); } } @@ -1005,7 +1006,7 @@ Track::use_captured_midi_sources (SourceList& srcs, CaptureInfos const & capture cerr << "add new region, len = " << (*ci)->samples << " @ " << (*ci)->start << endl; #endif - pl->add_region (midi_region, (*ci)->start + preroll_off, 1, _session.config.get_layered_record_mode ()); + pl->add_region (midi_region, timepos_t ((*ci)->start + preroll_off), 1, _session.config.get_layered_record_mode ()); } pl->thaw (); @@ -1039,15 +1040,15 @@ Track::use_captured_audio_sources (SourceList& srcs, CaptureInfos const & captur try { PropertyList plist; - plist.add (Properties::start, afs->last_capture_start_sample()); - plist.add (Properties::length, afs->length(0)); + plist.add (Properties::start, timecnt_t (afs->last_capture_start_sample(), timepos_t (Temporal::AudioTime))); + plist.add (Properties::length, afs->length()); plist.add (Properties::name, whole_file_region_name); boost::shared_ptr rx (RegionFactory::create (srcs, plist)); rx->set_automatic (true); rx->set_whole_file (true); region = boost::dynamic_pointer_cast (rx); - region->special_set_position (afs->natural_position()); + region->special_set_position (timepos_t (afs->natural_position())); } @@ -1084,14 +1085,14 @@ Track::use_captured_audio_sources (SourceList& srcs, CaptureInfos const & captur PropertyList plist; - plist.add (Properties::start, buffer_position); - plist.add (Properties::length, (*ci)->samples); + plist.add (Properties::start, timecnt_t (buffer_position, timepos_t::zero (false))); + plist.add (Properties::length, timecnt_t ((*ci)->samples, timepos_t::zero (false))); plist.add (Properties::name, region_name); boost::shared_ptr rx (RegionFactory::create (srcs, plist)); region = boost::dynamic_pointer_cast (rx); if (preroll_off > 0) { - region->trim_front (buffer_position + preroll_off); + region->trim_front (timepos_t (buffer_position + preroll_off)); } } @@ -1100,7 +1101,7 @@ Track::use_captured_audio_sources (SourceList& srcs, CaptureInfos const & captur continue; /* XXX is this OK? */ } - pl->add_region (region, (*ci)->start + preroll_off, 1, _session.config.get_layered_record_mode()); + pl->add_region (region, timepos_t ((*ci)->start + preroll_off), 1, _session.config.get_layered_record_mode()); pl->set_layer (region, DBL_MAX); buffer_position += (*ci)->samples; diff --git a/libs/ardour/transient_detector.cc b/libs/ardour/transient_detector.cc index bbf61ed795..4324d54aa7 100644 --- a/libs/ardour/transient_detector.cc +++ b/libs/ardour/transient_detector.cc @@ -51,7 +51,7 @@ TransientDetector::operational_identifier() } int -TransientDetector::run (const std::string& path, Readable* src, uint32_t channel, AnalysisFeatureList& results) +TransientDetector::run (const std::string& path, AudioReadable* src, uint32_t channel, AnalysisFeatureList& results) { current_results = &results; int ret = analyse (path, src, channel); @@ -140,7 +140,7 @@ TransientDetector::cleanup_transients (AnalysisFeatureList& t, float sr, float g } void -TransientDetector::update_positions (Readable* src, uint32_t channel, AnalysisFeatureList& positions) +TransientDetector::update_positions (AudioReadable* src, uint32_t channel, AnalysisFeatureList& positions) { int const buff_size = 1024; int const step_size = 64; diff --git a/libs/ardour/wscript b/libs/ardour/wscript index ce7121eaa7..e18c768d3e 100644 --- a/libs/ardour/wscript +++ b/libs/ardour/wscript @@ -47,7 +47,6 @@ libardour_sources = [ 'automation_list.cc', 'automation_watch.cc', 'beatbox.cc', - 'beats_samples_converter.cc', 'broadcast_info.cc', 'buffer.cc', 'buffer_manager.cc', @@ -136,7 +135,6 @@ libardour_sources = [ 'midi_model.cc', 'midi_patch_manager.cc', 'midi_playlist.cc', - 'midi_playlist_source.cc', 'midi_port.cc', 'midi_region.cc', 'midi_ring_buffer.cc', @@ -256,7 +254,6 @@ libardour_sources = [ 'revision.cc', 'rt_midibuffer.cc', 'template_utils.cc', - 'tempo.cc', 'tempo_map_importer.cc', 'thawlist.cc', 'thread_buffers.cc',