temporal: TempoMap::use() returns a const ptr to enforce semantics (library version)
This commit leaves two issues outstanding: 1. unclear/ugly semantics for drag operations that reset the GUI thread's tempo map to the writable copy 2. undo/redo for the tempo map These will be addressed in future commits
This commit is contained in:
parent
3d395585c1
commit
7c3268d12f
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -111,7 +111,9 @@ Session::memento_command_factory(XMLNode *n)
|
||||
return new MementoCommand<Locations>(*_locations, before, after);
|
||||
|
||||
} else if (type_name == "Temporal::TempoMap") {
|
||||
return new MementoCommand<TempoMap>(*TempoMap::use(), before, after);
|
||||
|
||||
#warning NUTEMPO how to reconstruct memento commands for a tempo map
|
||||
// return new MementoCommand<TempoMap>(*TempoMap::fetch(), 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())) {
|
||||
|
@ -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 (...) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 ());
|
||||
|
||||
|
@ -44,7 +44,7 @@ std::string Tempo::xml_node_name = X_("Tempo");
|
||||
std::string Meter::xml_node_name = X_("Meter");
|
||||
|
||||
SerializedRCUManager<TempoMap> TempoMap::_map_mgr (0);
|
||||
thread_local TempoMap::SharedPtr TempoMap::_tempo_map_p;
|
||||
thread_local TempoMap::WritableSharedPtr TempoMap::_tempo_map_p;
|
||||
PBD::Signal0<void> 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).
|
||||
*
|
||||
|
@ -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<TempoMap> SharedPtr;
|
||||
typedef boost::shared_ptr<TempoMap const> SharedPtr;
|
||||
typedef boost::shared_ptr<TempoMap> WritableSharedPtr;
|
||||
private:
|
||||
static thread_local SharedPtr _tempo_map_p;
|
||||
static thread_local WritableSharedPtr _tempo_map_p;
|
||||
static SerializedRCUManager<TempoMap> _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 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<Point*> Metrics;
|
||||
typedef std::list<Point const *> 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;
|
||||
|
Loading…
Reference in New Issue
Block a user