diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc index c96952a36c..59b3650955 100644 --- a/libs/ardour/audioengine.cc +++ b/libs/ardour/audioengine.cc @@ -289,7 +289,7 @@ AudioEngine::process_callback (pframes_t nframes) thread_init_callback (NULL); } - Temporal::TempoMap::SharedPtr current_map = Temporal::TempoMap::read (); + Temporal::TempoMap::WritableSharedPtr current_map = Temporal::TempoMap::read (); if (current_map != Temporal::TempoMap::use()) { Temporal::TempoMap::set (current_map); if (_session) { diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index 8dfb92a606..908ba10757 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -7368,12 +7368,13 @@ Session::listening () const void Session::maybe_update_tempo_from_midiclock_tempo (float bpm) { - TempoMap::SharedPtr tmap (TempoMap::use()); + TempoMap::WritableSharedPtr tmap (TempoMap::write_copy()); if (tmap->n_tempos() == 1) { Temporal::TempoMetric const & metric (tmap->metric_at (0)); if (fabs (metric.tempo().note_types_per_minute() - bpm) > (0.01 * metric.tempo().note_types_per_minute())) { tmap->change_tempo (metric.get_editable_tempo(), Tempo (bpm, 4.0, bpm)); + TempoMap::update (tmap); } } } diff --git a/libs/ardour/session_command.cc b/libs/ardour/session_command.cc index a35d2f76c1..6082b1c1eb 100644 --- a/libs/ardour/session_command.cc +++ b/libs/ardour/session_command.cc @@ -111,7 +111,9 @@ Session::memento_command_factory(XMLNode *n) return new MementoCommand(*_locations, before, after); } else if (type_name == "Temporal::TempoMap") { - return new MementoCommand(*TempoMap::use(), before, after); + +#warning NUTEMPO how to reconstruct memento commands for a tempo map + // return new MementoCommand(*TempoMap::fetch(), before, after); } else if (type_name == "ARDOUR::Playlist" || type_name == "ARDOUR::AudioPlaylist" || type_name == "ARDOUR::MidiPlaylist") { if (boost::shared_ptr pl = _playlists->by_name(child->property("name")->value())) { diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index 43d33ea8a9..fd03a4cbce 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -1589,7 +1589,7 @@ Session::set_state (const XMLNode& node, int version) goto out; } else { try { - TempoMap::SharedPtr tmap = TempoMap::write_copy (); /* get writable copy of current tempo map */ + TempoMap::WritableSharedPtr tmap = TempoMap::write_copy (); /* get writable copy of current tempo map */ tmap->set_state (*child, version); /* reset its state */ TempoMap::update (tmap); /* update the global tempo map manager */ } catch (...) { diff --git a/libs/ardour/tempo_map_importer.cc b/libs/ardour/tempo_map_importer.cc index e51c02ca49..93c27daa80 100644 --- a/libs/ardour/tempo_map_importer.cc +++ b/libs/ardour/tempo_map_importer.cc @@ -99,7 +99,7 @@ TempoMapImporter::_cancel_move () void TempoMapImporter::_move () { - TempoMap::SharedPtr tmap (TempoMap::write_copy()); + TempoMap::WritableSharedPtr tmap (TempoMap::write_copy()); tmap->set_state (xml_tempo_map, Stateful::current_state_version); TempoMap::update (tmap); } diff --git a/libs/surfaces/websockets/transport.cc b/libs/surfaces/websockets/transport.cc index 474bf77db8..58b98e2ddd 100644 --- a/libs/surfaces/websockets/transport.cc +++ b/libs/surfaces/websockets/transport.cc @@ -38,7 +38,7 @@ ArdourTransport::set_tempo (double bpm) { bpm = std::max (0.01, bpm); - TempoMap::SharedPtr tmap (TempoMap::write_copy()); + TempoMap::WritableSharedPtr tmap (TempoMap::write_copy()); Tempo tempo (bpm, tmap->metric_at (0).tempo().note_type ()); diff --git a/libs/temporal/tempo.cc b/libs/temporal/tempo.cc index ce5bbc5a58..3924524c9a 100644 --- a/libs/temporal/tempo.cc +++ b/libs/temporal/tempo.cc @@ -44,7 +44,7 @@ std::string Tempo::xml_node_name = X_("Tempo"); std::string Meter::xml_node_name = X_("Meter"); SerializedRCUManager TempoMap::_map_mgr (0); -thread_local TempoMap::SharedPtr TempoMap::_tempo_map_p; +thread_local TempoMap::WritableSharedPtr TempoMap::_tempo_map_p; PBD::Signal0 TempoMap::MapChanged; void @@ -1802,7 +1802,7 @@ TempoMap::_get_tempo_and_meter (typename const_traits_t::tempo_point_type & tp, } void -TempoMap::get_grid (TempoMapPoints& ret, superclock_t start, superclock_t end, uint32_t bar_mod) +TempoMap::get_grid (TempoMapPoints& ret, superclock_t start, superclock_t end, uint32_t bar_mod) const { /* note: @param bar_mod is "bar modulo", and describes the N in "give me every Nth bar". If the caller wants every 4th bar, bar_mod == @@ -2119,7 +2119,7 @@ TempoMap::get_grid (TempoMapPoints& ret, superclock_t start, superclock_t end, u } uint32_t -TempoMap::count_bars (Beats const & start, Beats const & end) +TempoMap::count_bars (Beats const & start, Beats const & end) const { TempoMapPoints bar_grid; superclock_t s (superclock_at (start)); @@ -3181,7 +3181,7 @@ void TempoMap::MementoBinder::set_state (XMLNode const & node, int version) const { /* fetch a writable copy of this thread's tempo map */ - TempoMap::SharedPtr map (write_copy()); + TempoMap::WritableSharedPtr map (write_copy()); /* change the state of the copy */ map->set_state (node, version); /* do the update step of RCU. This will also update this thread's map pointer */ @@ -3191,19 +3191,19 @@ TempoMap::MementoBinder::set_state (XMLNode const & node, int version) const void TempoMap::init () { - SharedPtr new_map (new TempoMap (Tempo (120, 4), Meter (4, 4))); + WritableSharedPtr new_map (new TempoMap (Tempo (120, 4), Meter (4, 4))); _map_mgr.init (new_map); fetch (); } -TempoMap::SharedPtr +TempoMap::WritableSharedPtr TempoMap::write_copy() { return _map_mgr.write_copy(); } int -TempoMap::update (TempoMap::SharedPtr m) +TempoMap::update (TempoMap::WritableSharedPtr m) { if (!_map_mgr.update (m)) { return -1; @@ -3231,7 +3231,7 @@ TempoMap::abort_update () } void -TempoMap::midi_clock_beat_at_or_after (samplepos_t const pos, samplepos_t& clk_pos, uint32_t& clk_beat) +TempoMap::midi_clock_beat_at_or_after (samplepos_t const pos, samplepos_t& clk_pos, uint32_t& clk_beat) const { /* Sequences are always assumed to start on a MIDI Beat of 0 (ie, the downbeat). * diff --git a/libs/temporal/temporal/tempo.h b/libs/temporal/temporal/tempo.h index 7cc64dac08..f8c502d911 100644 --- a/libs/temporal/temporal/tempo.h +++ b/libs/temporal/temporal/tempo.h @@ -598,7 +598,7 @@ class /*LIBTEMPORAL_API*/ MusicTimePoint : public bartime_hook, public virtual class LIBTEMPORAL_API TempoMapPoint : public Point, public TempoMetric { public: - TempoMapPoint (TempoMap & map, TempoMetric const & tm, superclock_t sc, Beats const & q, BBT_Time const & bbt) + TempoMapPoint (TempoMap const & map, TempoMetric const & tm, superclock_t sc, Beats const & q, BBT_Time const & bbt) : Point (map, sc, q, bbt), TempoMetric (tm), _floating (false) {} ~TempoMapPoint () {} @@ -658,24 +658,35 @@ class /*LIBTEMPORAL_API*/ TempoMap : public PBD::StatefulDestructible * */ public: - typedef boost::shared_ptr SharedPtr; + typedef boost::shared_ptr SharedPtr; + typedef boost::shared_ptr WritableSharedPtr; private: - static thread_local SharedPtr _tempo_map_p; + static thread_local WritableSharedPtr _tempo_map_p; static SerializedRCUManager _map_mgr; public: LIBTEMPORAL_API static void init (); - LIBTEMPORAL_API static void update_thread_tempo_map() { _tempo_map_p = _map_mgr.reader(); } + LIBTEMPORAL_API static void update_thread_tempo_map() { _tempo_map_p = _map_mgr.reader(); } LIBTEMPORAL_API static SharedPtr use() { assert (_tempo_map_p); return _tempo_map_p; } - LIBTEMPORAL_API static SharedPtr fetch() { update_thread_tempo_map(); return use(); } - LIBTEMPORAL_API static SharedPtr read() { return _map_mgr.reader(); } - LIBTEMPORAL_API static void set (SharedPtr new_map) { _tempo_map_p = new_map; /* new_map must have been fetched with read() */ } + LIBTEMPORAL_API static SharedPtr fetch() { update_thread_tempo_map(); return _tempo_map_p; } - LIBTEMPORAL_API static SharedPtr write_copy(); - LIBTEMPORAL_API static void fetch_writable() { _tempo_map_p = write_copy(); } - LIBTEMPORAL_API static int update (SharedPtr m); + /* Used only by the ARDOUR::AudioEngine API to reset the process thread + * tempo map only when it has changed. + */ + + LIBTEMPORAL_API static WritableSharedPtr read() { return _map_mgr.reader(); } + LIBTEMPORAL_API static void set (WritableSharedPtr new_map) { _tempo_map_p = new_map; /* new_map must have been fetched with read() */ } + + /* API for typical tempo map changes */ + + LIBTEMPORAL_API static WritableSharedPtr write_copy(); + LIBTEMPORAL_API static int update (WritableSharedPtr m); LIBTEMPORAL_API static void abort_update (); + /* API to be reviewed */ + + LIBTEMPORAL_API static WritableSharedPtr fetch_writable() { _tempo_map_p = write_copy(); return _tempo_map_p; } + /* and now on with the rest of the show ... */ public: @@ -727,11 +738,11 @@ class /*LIBTEMPORAL_API*/ TempoMap : public PBD::StatefulDestructible * offer one that uses an STL container instead. */ - typedef std::list Metrics; + typedef std::list Metrics; - void get_metrics (Metrics& m) { - for (Points::iterator t = _points.begin(); t != _points.end(); ++t) { - m.push_back (&*t); + void get_metrics (Metrics& m) const { + for (auto const & p : _points) { + m.push_back (&p); } } @@ -845,8 +856,8 @@ class /*LIBTEMPORAL_API*/ TempoMap : public PBD::StatefulDestructible LIBTEMPORAL_API BBT_Time bbt_walk (BBT_Time const &, BBT_Offset const &) const; - LIBTEMPORAL_API void get_grid (TempoMapPoints & points, superclock_t start, superclock_t end, uint32_t bar_mod = 0); - LIBTEMPORAL_API uint32_t count_bars (Beats const & start, Beats const & end); + LIBTEMPORAL_API void get_grid (TempoMapPoints & points, superclock_t start, superclock_t end, uint32_t bar_mod = 0) const; + LIBTEMPORAL_API uint32_t count_bars (Beats const & start, Beats const & end) const; struct EmptyTempoMapException : public std::exception { virtual const char* what() const throw() { return "TempoMap is empty"; } @@ -879,7 +890,7 @@ class /*LIBTEMPORAL_API*/ TempoMap : public PBD::StatefulDestructible LIBTEMPORAL_API Beats quarters_at_sample (samplepos_t sc) const { return quarters_at_superclock (samples_to_superclock (sc, TEMPORAL_SAMPLE_RATE)); } LIBTEMPORAL_API Beats quarters_at_superclock (superclock_t sc) const; - LIBTEMPORAL_API void midi_clock_beat_at_or_after (samplepos_t const pos, samplepos_t& clk_pos, uint32_t& clk_beat); + LIBTEMPORAL_API void midi_clock_beat_at_or_after (samplepos_t const pos, samplepos_t& clk_pos, uint32_t& clk_beat) const; private: Tempos _tempos;