remove/hide Session::tempo_map() and use TempoMap::use() instead (thread local shared ptr)

This commit is contained in:
Paul Davis 2020-11-27 12:40:58 -07:00
parent 60d1c5f722
commit 79763893b3
20 changed files with 64 additions and 62 deletions

View File

@ -828,8 +828,8 @@ public:
bool loop_is_possible () const;
PBD::Signal0<void> PunchLoopConstraintChange;
Temporal::TempoMap& tempo_map() { *Temporal::TempoMap::fetch(); }
const Temporal::TempoMap& tempo_map() const { return *Temporal::TempoMap::fetch(); }
// 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; }

View File

@ -2509,7 +2509,8 @@ LuaBindings::common (lua_State* L)
.addFunction ("master_out", &Session::master_out)
.addFunction ("add_internal_send", (void (Session::*)(boost::shared_ptr<Route>, boost::shared_ptr<Processor>, boost::shared_ptr<Route>))&Session::add_internal_send)
.addFunction ("add_internal_sends", &Session::add_internal_sends)
.addFunction ("tempo_map", (TempoMap& (Session::*)())&Session::tempo_map)
#warning NUTEMPO allow lua access to the tempo map
// .addFunction ("tempo_map", (TempoMap& (Session::*)())&Session::tempo_map)
.addFunction ("locations", &Session::locations)
.addFunction ("soloing", &Session::soloing)
.addFunction ("listening", &Session::listening)

View File

@ -2645,9 +2645,9 @@ LV2Plugin::connect_and_run(BufferSet& bufs,
speed = end > 0 ? speed : 0;
samplepos_t start0 = std::max (samplepos_t (0), start);
TempoMap& tmap = _session.tempo_map();
TempoMap::SharedPtr tmap (TempoMap::use());
TempoMapPoints tempo_map_points;
tmap.get_grid (tempo_map_points, start, end, 0);
tmap->get_grid (tempo_map_points, start, end, 0);
TempoMapPoints::const_iterator tempo_map_point = tempo_map_points.begin();
TempoMapPoint first_tempo_map_point = tempo_map_points.front();
@ -2659,7 +2659,7 @@ LV2Plugin::connect_and_run(BufferSet& bufs,
float bpm = tmap.tempo_at_sample (start0).note_types_per_minute();
TempoMapPoints tempo_map_points;
tmap.get_grid (tempo_map_points, start0, end, 0);
tmap->get_grid (tempo_map_points, start0, end, 0);
TempoMapPoint first_tempo_map_point = tempo_map_points.front();
/* note that this is not necessarily quarter notes */
@ -3123,7 +3123,7 @@ LV2Plugin::connect_and_run(BufferSet& bufs,
* Note: for no-midi plugins, we only ever send information at cycle-start,
* so it needs to be realative to that.
*/
TempoMetric metric (tmap.metric_at (start));
TempoMetric metric (tmap->metric_at (start));
_current_bpm = metric.tempo().note_types_per_minute();
Temporal::BBT_Time bbt (metric.bbt_at (start));
double beatpos = (bbt.bars - 1) * metric.divisions_per_bar()

View File

@ -157,7 +157,7 @@ MIDIClock_TransportMaster::pre_process (MIDI::pframes_t nframes, samplepos_t now
void
MIDIClock_TransportMaster::calculate_one_ppqn_in_samples_at(samplepos_t time)
{
const Temporal::TempoMetric& metric = _session->tempo_map().metric_at (time);
const Temporal::TempoMetric& metric = Temporal::TempoMap::use()->metric_at (time);
const double samples_per_quarter_note = metric.tempo().samples_per_quarter_note (ENGINE->sample_rate());
one_ppqn_in_samples = samples_per_quarter_note / double (ppqn);

View File

@ -272,7 +272,8 @@ Session::Session (AudioEngine &eng,
, ltc_timecode_offset (0)
, ltc_timecode_negative_offset (false)
, midi_control_ui (0)
, _tempo_map (0)
, _punch_or_loop (NoConstraint)
, current_usecs_per_track (1000)
, _all_route_group (new RouteGroup (*this, "all"))
, routes (new RouteList)
, _adding_routes_in_progress (false)
@ -429,7 +430,6 @@ Session::Session (AudioEngine &eng,
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;
@ -915,7 +915,6 @@ Session::destroy ()
delete _locations; _locations = 0;
delete midi_clock;
delete _tempo_map;
/* clear event queue, the session is gone, nobody is interested in
* those anymore, but they do leak memory if not removed
@ -2195,7 +2194,7 @@ Session::preroll_samples (samplepos_t pos) const
{
const float pr = Config->get_preroll_seconds();
if (pos >= 0 && pr < 0) {
Temporal::TempoMetric const & metric (_tempo_map->metric_at (pos));
Temporal::TempoMetric const & metric (TempoMap::use()->metric_at (pos));
return metric.samples_per_bar (sample_rate()) * -pr;
}
if (pr < 0) {
@ -7427,10 +7426,12 @@ Session::listening () const
void
Session::maybe_update_tempo_from_midiclock_tempo (float bpm)
{
if (_tempo_map->n_tempos() == 1) {
Temporal::TempoMetric const & metric (_tempo_map->metric_at (0));
TempoMap::SharedPtr tmap (TempoMap::use());
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())) {
_tempo_map->change_tempo (metric.tempo(), Tempo (bpm, 4.0, bpm));
tmap->change_tempo (metric.tempo(), Tempo (bpm, 4.0, bpm));
}
}
}

View File

@ -124,7 +124,7 @@ Session::click (samplepos_t cycle_start, samplecnt_t nframes)
const samplepos_t end = start + move;
_click_points.clear ();
_tempo_map->get_grid (_click_points, samples_to_superclock (start, sample_rate()), samples_to_superclock (end, sample_rate()));
TempoMap::use()->get_grid (_click_points, samples_to_superclock (start, sample_rate()), samples_to_superclock (end, sample_rate()));
if (distance (_click_points.begin(), _click_points.end()) == 0) {
start += move;

View File

@ -110,8 +110,8 @@ Session::memento_command_factory(XMLNode *n)
} else if (type_name == "ARDOUR::Locations") {
return new MementoCommand<Locations>(*_locations, before, after);
} else if (type_name == "ARDOUR::TempoMap") {
return new MementoCommand<TempoMap>(*_tempo_map, before, after);
} else if (type_name == "Temporal::TempoMap") {
return new MementoCommand<TempoMap>(*TempoMap::use(), before, after);
} else if (type_name == "ARDOUR::Playlist" || type_name == "ARDOUR::AudioPlaylist" || type_name == "ARDOUR::MidiPlaylist") {
if (boost::shared_ptr<Playlist> pl = _playlists->by_name(child->property("name")->value())) {

View File

@ -260,19 +260,7 @@ Session::post_engine_init ()
_engine.Halted.connect_same_thread (*this, boost::bind (&Session::engine_halted, this));
_engine.Xrun.connect_same_thread (*this, boost::bind (&Session::xrun_recovery, this));
try {
/* tempo map requires sample rate knowledge */
delete _tempo_map;
_tempo_map = new Temporal::TempoMap (Temporal::Tempo (120), Temporal::Meter (4, 4));
_tempo_map->Changed.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this));
} catch (std::exception const & e) {
error << _("Unexpected exception during session setup: ") << e.what() << endmsg;
return -2;
} catch (...) {
error << _("Unknown exception during session setup") << endmsg;
return -3;
}
#warning NUTEMPO does session need to know about tempo map changes?
try {
/* MidiClock requires a tempo map */

View File

@ -41,6 +41,7 @@
using namespace std;
using namespace ARDOUR;
using namespace PBD;
using namespace Temporal;
#define TFSM_EVENT(evtype) { _transport_fsm->enqueue (new TransportFSM::Event (evtype)); }
@ -49,7 +50,7 @@ using namespace PBD;
void
Session::bbt_time (timepos_t const & when, Temporal::BBT_Time& bbt)
{
bbt = _tempo_map->bbt_at (when);
bbt = TempoMap::use()->bbt_at (when);
}
/* Timecode TIME */
@ -241,7 +242,7 @@ Session::convert_to_samples (AnyTime const & position)
switch (position.type) {
case AnyTime::BBT:
return Temporal::superclock_to_samples (_tempo_map->superclock_at (position.bbt), _current_sample_rate);
return Temporal::superclock_to_samples (TempoMap::use()->superclock_at (position.bbt), _current_sample_rate);
break;
case AnyTime::Timecode:
@ -277,7 +278,7 @@ Session::any_duration_to_samples (samplepos_t position, AnyTime const & duration
switch (duration.type) {
case AnyTime::BBT:
return Temporal::superclock_to_samples (_tempo_map->superclock_plus_bbt (Temporal::samples_to_superclock (position, _current_sample_rate), duration.bbt), _current_sample_rate) - position;
return Temporal::superclock_to_samples (TempoMap::use()->superclock_plus_bbt (Temporal::samples_to_superclock (position, _current_sample_rate), duration.bbt), _current_sample_rate) - position;
break;
case AnyTime::Timecode:

View File

@ -522,16 +522,18 @@ Session::start_transport (bool after_loop)
if ((actively_recording () || (config.get_punch_in () && get_record_enabled ()))
&& click_data && (config.get_count_in () || _count_in_once)) {
TempoMap::SharedPtr tmap (TempoMap::use());
_count_in_once = false;
/* calculate count-in duration (in audio samples)
* - use [fixed] tempo/meter at _transport_sample
* - calc duration of 1 bar + time-to-beat before or at transport_sample
*/
TempoMetric const & tempometric = _tempo_map->metric_at (_transport_sample);
TempoMetric const & tempometric = tmap->metric_at (_transport_sample);
const double num = tempometric.divisions_per_bar ();
/* XXX possible optimization: get meter and BBT time in one call */
const Temporal::BBT_Time bbt = _tempo_map->bbt_at (_transport_sample);
const Temporal::BBT_Time bbt = tmap->bbt_at (_transport_sample);
const double bar_fract = (double) bbt.beats / tempometric.divisions_per_bar();
_count_in_samples = tempometric.samples_per_bar (_current_sample_rate);

View File

@ -75,6 +75,7 @@ intptr_t Session::vst_callback (
static VstTimeInfo _timeinfo; // only uses as fallback
VstTimeInfo* timeinfo;
int32_t newflags = 0;
TempoMap::SharedPtr tmap (TempoMap::use());
if (effect && effect->ptr1) {
plug = (VSTPlugin *) (effect->ptr1);
@ -188,12 +189,12 @@ intptr_t Session::vst_callback (
timeinfo->sampleRate = session->sample_rate();
if (value & (kVstTempoValid)) {
const Tempo& t (session->tempo_map().metric_at (now).tempo());
const Tempo& t (tmap->metric_at (now).tempo());
timeinfo->tempo = t.quarter_notes_per_minute ();
newflags |= (kVstTempoValid);
}
if (value & (kVstTimeSigValid)) {
const Meter& ms (session->tempo_map().metric_at (now).meter());
const Meter& ms (tmap->metric_at (now).meter());
timeinfo->timeSigNumerator = ms.divisions_per_bar ();
timeinfo->timeSigDenominator = ms.note_value ();
newflags |= (kVstTimeSigValid);
@ -202,13 +203,13 @@ intptr_t Session::vst_callback (
Temporal::BBT_Time bbt;
try {
bbt = session->tempo_map().bbt_at (now);
bbt = tmap->bbt_at (now);
bbt.beats = 1;
bbt.ticks = 0;
/* exact quarter note */
double ppqBar = session->tempo_map().quarter_note_at (bbt);
double ppqBar = tmap->quarter_note_at (bbt);
/* quarter note at sample position (not rounded to note subdivision) */
double ppqPos = session->tempo_map().quarter_note_at (now);
double ppqPos = tmap->quarter_note_at (now);
if (value & (kVstPpqPosValid)) {
timeinfo->ppqPos = ppqPos;
newflags |= kVstPpqPosValid;
@ -314,7 +315,7 @@ intptr_t Session::vst_callback (
SHOW_CALLBACK ("audioMasterTempoAt");
// returns tempo (in bpm * 10000) at sample sample location passed in <value>
if (session) {
const Tempo& t (session->tempo_map().metric_at (value).tempo());
const Tempo& t (tmap->metric_at (value).tempo());
return t.quarter_notes_per_minute() * 1000;
} else {
return 0;

View File

@ -31,6 +31,7 @@
using namespace std;
using namespace PBD;
using namespace ARDOUR;
using namespace Temporal;
/**** Handler ***/
TempoMapImportHandler::TempoMapImportHandler (XMLTree const & source, Session & session) :
@ -98,5 +99,7 @@ TempoMapImporter::_cancel_move ()
void
TempoMapImporter::_move ()
{
session.tempo_map().set_state (xml_tempo_map, Stateful::current_state_version);
TempoMap::SharedPtr tmap (TempoMap::write_copy());
tmap->set_state (xml_tempo_map, Stateful::current_state_version);
TempoMap::update (tmap);
}

View File

@ -215,7 +215,7 @@ out:
double
MidiClockTicker::one_ppqn_in_samples (samplepos_t transport_position) const
{
Tempo const & tempo (_session->tempo_map().metric_at (transport_position).tempo());
Tempo const & tempo (TempoMap::use()->metric_at (transport_position).tempo());
const double samples_per_quarter_note = tempo.samples_per_quarter_note (_session->nominal_sample_rate());
return samples_per_quarter_note / 24.0;
}

View File

@ -115,7 +115,7 @@ JACKSession::timebase_callback (jack_transport_state_t /*state*/,
int /*new_position*/)
{
Temporal::BBT_Time bbt;
TempoMap& tempo_map (_session->tempo_map());
TempoMap::SharedPtr tempo_map (TempoMap::use());
samplepos_t tf;
/* see commit msg for e2c26e1b9 and Session::start_locate() for
@ -126,10 +126,10 @@ JACKSession::timebase_callback (jack_transport_state_t /*state*/,
/* BBT info */
TempoMetric metric (tempo_map.metric_at (tf));
TempoMetric metric (tempo_map->metric_at (tf));
try {
bbt = tempo_map.bbt_at (tf);
bbt = tempo_map->bbt_at (tf);
pos->bar = bbt.bars;
pos->beat = bbt.beats;

View File

@ -548,8 +548,8 @@ BasicUI::jump_by_seconds (double secs, LocateTransportDisposition ltd)
void
BasicUI::jump_by_bars (int bars, LocateTransportDisposition ltd)
{
TempoMap& tmap (session->tempo_map());
Temporal::BBT_Time bbt (tmap.bbt_at (session->transport_sample()));
TempoMap::SharedPtr tmap (TempoMap::use());
Temporal::BBT_Time bbt (tmap->bbt_at (session->transport_sample()));
bars += bbt.bars;
if (bars < 0) {

View File

@ -268,7 +268,7 @@ FaderPort8::periodic ()
_timecode = Timecode::timecode_format_time(TC);
char buf[16];
Temporal::BBT_Time BBT = session->tempo_map ().bbt_at (session->transport_sample ());
Temporal::BBT_Time BBT = Temporal::TempoMap::use()->bbt_at (session->transport_sample ());
snprintf (buf, sizeof (buf),
" %02" PRIu32 "|%02" PRIu32 "|%02" PRIu32 "|%02" PRIu32,
BBT.bars % 100, BBT.beats %100,

View File

@ -603,7 +603,7 @@ TrackMixLayout::update_clocks ()
}
char buf[16];
Temporal::BBT_Time BBT = session.tempo_map().bbt_at (pos);
Temporal::BBT_Time BBT = Temporal::TempoMap::use()->bbt_at (pos);
#define BBT_BAR_CHAR "|"

View File

@ -229,8 +229,10 @@ ArdourFeedback::observe_transport ()
boost::bind<void> (TransportObserver (), this), event_loop ());
sess.RecordStateChanged.connect (_transport_connections, MISSING_INVALIDATOR,
boost::bind<void> (RecordStateObserver (), this), event_loop ());
sess.tempo_map ().PropertyChanged.connect (_transport_connections, MISSING_INVALIDATOR,
boost::bind<void> (TempoObserver (), this), event_loop ());
#warning NUTEMPO this is not right. the actual map can change. static signal?
Temporal::TempoMap::use()->Changed.connect (_signal_connections, MISSING_INVALIDATOR,
boost::bind<void> (TempoObserver (), this), event_loop ());
}
void
@ -252,7 +254,7 @@ ArdourFeedback::observe_mixer ()
stripable->mute_control ()->Changed.connect (*it->second, MISSING_INVALIDATOR,
boost::bind<void> (StripMuteObserver (), this, strip_id), event_loop ());
observe_strip_plugins (strip_id, strip->plugins ());
}
}

View File

@ -27,18 +27,21 @@ using namespace Temporal;
double
ArdourTransport::tempo () const
{
const Tempo& tempo (session ().tempo_map ().metric_at (0).tempo());
const Tempo& tempo (TempoMap::use()->metric_at (0).tempo());
return tempo.note_types_per_minute ();
}
void
ArdourTransport::set_tempo (double bpm)
{
bpm = std::max (0.01, bpm);
TempoMap& tempo_map = session ().tempo_map ();
Tempo tempo (bpm, tempo_map.metric_at (0).tempo().note_type ());
#warning NUTEMPO need some API to do this
// tempo_map.add_tempo (tempo, 0.0, 0, AudioTime);
bpm = std::max (0.01, bpm);
TempoMap::SharedPtr tmap (TempoMap::write_copy());
Tempo tempo (bpm, tmap->metric_at (0).tempo().note_type ());
tmap->set_tempo (tempo, timepos_t());
TempoMap::update (tmap);
}
double

View File

@ -618,7 +618,7 @@ class LIBTEMPORAL_API TempoMap : public PBD::StatefulDestructible
static SerializedRCUManager<TempoMap> _map_mgr;
public:
static void update_thread_tempo_map() { _tempo_map_p = _map_mgr.reader(); }
static SharedPtr use() { return _tempo_map_p; }
static SharedPtr use() { assert (_tempo_map_p); return _tempo_map_p; }
static SharedPtr fetch() { update_thread_tempo_map(); return use(); }
static SharedPtr write_copy() { return _map_mgr.write_copy(); }
@ -663,6 +663,7 @@ class LIBTEMPORAL_API TempoMap : public PBD::StatefulDestructible
bool move_meter (MeterPoint const & point, timepos_t const & destination, bool push = false);
void set_time_domain (TimeDomain td);
int set_state (XMLNode const&, int version);
/* END OF MODIFYING METHODS */
@ -764,7 +765,6 @@ class LIBTEMPORAL_API TempoMap : public PBD::StatefulDestructible
PBD::Signal0<void> Changed;
XMLNode& get_state();
int set_state (XMLNode const&, int version);
typedef boost::intrusive::member_hook<TempoPoint,boost::intrusive::list_member_hook<>, &TempoPoint::_tempo_hook> TempoHookOption;
typedef boost::intrusive::member_hook<MeterPoint,boost::intrusive::list_member_hook<>, &MeterPoint::_meter_hook> MeterHookOption;