diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc index 4d29786102..7e028a9739 100644 --- a/gtk2_ardour/editor.cc +++ b/gtk2_ardour/editor.cc @@ -1373,7 +1373,6 @@ Editor::set_session (Session *t) _session->vca_manager().VCAAdded.connect (_session_connections, invalidator (*this), boost::bind (&Editor::add_vcas, this, _1), gui_context()); _session->RouteAdded.connect (_session_connections, invalidator (*this), boost::bind (&Editor::add_routes, this, _1), gui_context()); _session->DirtyChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::update_title, this), gui_context()); - _session->tempo_map().PropertyChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::tempo_map_property_changed, this, _1), gui_context()); _session->tempo_map().Changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::tempo_map_changed, this), gui_context()); _session->Located.connect (_session_connections, invalidator (*this), boost::bind (&Editor::located, this), gui_context()); _session->config.ParameterChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::parameter_changed, this, _1), gui_context()); diff --git a/gtk2_ardour/editor_audio_import.cc b/gtk2_ardour/editor_audio_import.cc index 1bb90eab3f..de3453ad7d 100644 --- a/gtk2_ardour/editor_audio_import.cc +++ b/gtk2_ardour/editor_audio_import.cc @@ -284,7 +284,7 @@ Editor::import_smf_tempo_map (Evoral::SMF const & smf, timepos_t const & pos) const samplecnt_t sample_rate = _session->sample_rate (); #warning NUTEMPO need to be able to create a tempo map with no entries // TempoMap new_map (sample_rate); - TempoMap new_map (Tempo (120), Meter (4, 4)); + TempoMap::SharedPtr new_map (new TempoMap (Tempo (120), Meter (4, 4))); Meter last_meter (4.0, 4.0); bool have_initial_meter = false; @@ -301,22 +301,20 @@ Editor::import_smf_tempo_map (Evoral::SMF const & smf, timepos_t const & pos) #warning NUTEMPO figure this out when i have a brain // new_map.set_tempo (tempo, Temporal::Beats (t->time_pulses/ (double)smf.ppqn() / 4.0); if (!(meter == last_meter)) { - bbt = new_map.bbt_at (Beats::from_double (t->time_pulses/(double)smf.ppqn())); - new_map.set_meter (meter, bbt); + bbt = new_map->bbt_at (Beats::from_double (t->time_pulses/(double)smf.ppqn())); + new_map->set_meter (meter, bbt); } } else { - new_map.set_meter (meter, bbt); - new_map.set_tempo (tempo, bbt); + new_map->set_meter (meter, bbt); + new_map->set_tempo (tempo, bbt); have_initial_meter = true; - } last_meter = meter; } -#warning NUTEMPO need an assignment API for TempoMap - //_session->tempo_map() = new_map; + TempoMap::update (new_map); } void diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index d95319a810..dc33d9bb0b 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -828,8 +828,8 @@ public: bool loop_is_possible () const; PBD::Signal0 PunchLoopConstraintChange; - Temporal::TempoMap& tempo_map() { return *_tempo_map; } - const Temporal::TempoMap& tempo_map() const { return *_tempo_map; } + Temporal::TempoMap& tempo_map() { *Temporal::TempoMap::fetch(); } + const Temporal::TempoMap& tempo_map() const { return *Temporal::TempoMap::fetch(); } void maybe_update_tempo_from_midiclock_tempo (float bpm); unsigned int get_xrun_count () const {return _xrun_count; } @@ -1867,7 +1867,6 @@ private: int send_full_time_code (samplepos_t, pframes_t nframes); void send_song_position_pointer (samplepos_t); - Temporal::TempoMap *_tempo_map; void tempo_map_changed (); /* edit/mix groups */ diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index d4a08f33f2..b37d6b6343 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -153,6 +153,7 @@ using namespace std; using namespace ARDOUR; using namespace PBD; +using namespace Temporal; #define DEBUG_UNDO_HISTORY(msg) DEBUG_TRACE (PBD::DEBUG::UndoHistory, string_compose ("%1: %2\n", __LINE__, msg)); @@ -1517,7 +1518,7 @@ Session::state (bool save_template, snapshot_t snapshot_type, bool only_used_ass } node->add_child_nocopy (_speakers->get_state()); - node->add_child_nocopy (_tempo_map->get_state()); + node->add_child_nocopy (TempoMap::fetch()->get_state()); node->add_child_nocopy (get_control_protocol_state()); if (_extra_xml) { @@ -1659,8 +1660,13 @@ Session::set_state (const XMLNode& node, int version) if ((child = find_named_node (node, "TempoMap")) == 0) { error << _("Session: XML state has no Tempo Map section") << endmsg; goto out; - } else if (_tempo_map->set_state (*child, version)) { - goto out; + } else { + try { + TempoMap::SharedPtr new_map (new TempoMap (*child, version)); + TempoMap::update (new_map); + } catch (...) { + goto out; + } } if ((child = find_named_node (node, "Locations")) == 0) { diff --git a/libs/temporal/tempo.cc b/libs/temporal/tempo.cc index 1827c6ea5a..34f1818fac 100644 --- a/libs/temporal/tempo.cc +++ b/libs/temporal/tempo.cc @@ -567,28 +567,31 @@ TempoMapPoint::end_float () /* TEMPOMAP */ TempoMap::TempoMap (Tempo const & initial_tempo, Meter const & initial_meter) - : _initial_tempo (*this, initial_tempo, 0, Beats(), BBT_Time()) - , _initial_meter (*this, initial_meter, 0, Beats(), BBT_Time()) - , _initial_music_time (*this) { - _tempos.push_back (_initial_tempo); - _meters.push_back (_initial_meter); - _bartimes.push_back (_initial_music_time); + TempoPoint* tp = new TempoPoint (*this, initial_tempo, 0, Beats(), BBT_Time()); + MeterPoint* mp = new MeterPoint (*this, initial_meter, 0, Beats(), BBT_Time()); + MusicTimePoint* mtp = new MusicTimePoint (*this); - _points.push_back (_initial_tempo); - _points.push_back (_initial_meter); - _points.push_back (_initial_music_time); + _tempos.push_back (*tp); + _meters.push_back (*mp); + _bartimes.push_back (*mtp); + + _points.push_back (*tp); + _points.push_back (*mp); + _points.push_back (*mtp); } TempoMap::~TempoMap() { } +TempoMap::TempoMap (XMLNode const & node, int version) +{ + set_state (node, version); +} + TempoMap::TempoMap (TempoMap const & other) : _time_domain (other.time_domain()) - , _initial_tempo (other.metric_at (0).tempo()) - , _initial_meter (other.metric_at (0).meter()) - , _initial_music_time (*this) { #warning NUTEMPO since these lists are intrusive we must actually rebuild them // _meters = other._meters; diff --git a/libs/temporal/temporal/tempo.h b/libs/temporal/temporal/tempo.h index d47e1dc646..3e2c1e9802 100644 --- a/libs/temporal/temporal/tempo.h +++ b/libs/temporal/temporal/tempo.h @@ -621,11 +621,15 @@ class LIBTEMPORAL_API TempoMap : public PBD::StatefulDestructible static SharedPtr use() { return _tempo_map_p; } static SharedPtr fetch() { update_thread_tempo_map(); return use(); } + static SharedPtr write_copy() { return _map_mgr.write_copy(); } + static void update (SharedPtr m) { _map_mgr.update (m); _tempo_map_p = _map_mgr.reader(); } + /* and now on with the rest of the show ... */ public: TempoMap (Tempo const & initial_tempo, Meter const & initial_meter); TempoMap (TempoMap const &); + TempoMap (XMLNode const &, int version); ~TempoMap(); void sample_rate_changed (samplecnt_t new_sr); @@ -779,9 +783,6 @@ class LIBTEMPORAL_API TempoMap : public PBD::StatefulDestructible Points _points; TimeDomain _time_domain; - TempoPoint _initial_tempo; - MeterPoint _initial_meter; - MusicTimePoint _initial_music_time; /* These return the TempoMetric in effect at the given time. If can_match is true, then the TempoMetric may refer to a Tempo or