next iteration of changes to handle time domain bounces as undoable

This commit is contained in:
Paul Davis 2023-08-14 23:38:33 -06:00
parent 5e3cdf285e
commit 076cb86912
28 changed files with 286 additions and 235 deletions

View File

@ -161,12 +161,12 @@ class LIBARDOUR_API AudioRegion : public Region, public AudioReadable
/* automation */
std::shared_ptr<Evoral::Control>
control(const Evoral::Parameter& id, bool create=false) {
control(const Evoral::Parameter& id, bool create=false) {
return _automatable.control(id, create);
}
virtual std::shared_ptr<const Evoral::Control>
control(const Evoral::Parameter& id) const {
control(const Evoral::Parameter& id) const {
return _automatable.control(id);
}

View File

@ -34,6 +34,7 @@
#include "evoral/ControlSet.h"
#include "temporal/domain_swap.h"
#include "temporal/domain_provider.h"
#include "ardour/libardour_visibility.h"
@ -50,7 +51,7 @@ class AutomationControl;
/* The inherited ControlSet is virtual because AutomatableSequence inherits
* from this AND EvoralSequence, which is also a ControlSet
*/
class LIBARDOUR_API Automatable : virtual public Evoral::ControlSet, public Slavable, public Temporal::TimeDomainProvider
class LIBARDOUR_API Automatable : virtual public Evoral::ControlSet, public Slavable, public Temporal::TimeDomainProvider, public Temporal::TimeDomainSwapper
{
public:
Automatable(Session&, Temporal::TimeDomainProvider const &);
@ -119,6 +120,9 @@ public:
PBD::Signal0<void> AutomationStateChanged;
void start_domain_bounce (Temporal::DomainBounceInfo&);
void finish_domain_bounce (Temporal::DomainBounceInfo&);
protected:
Session& _a_session;

View File

@ -38,6 +38,8 @@
#include "pbd/stateful.h"
#include "pbd/statefuldestructible.h"
#include "temporal/domain_provider.h"
#include "temporal/domain_swap.h"
#include "temporal/types.h"
#include "ardour/ardour.h"
@ -173,8 +175,12 @@ public:
Temporal::TimeDomain position_time_domain() const { return _start.time_domain(); }
void globally_change_time_domain (Temporal::TimeDomain from, Temporal::TimeDomain to);
void change_time_domain (Temporal::TimeDomain from, Temporal::TimeDomain to);
/* Similar to, but not identical to the Temporal::TimeDomainSwapper API */
void start_domain_bounce (Temporal::DomainBounceInfo&);
void finish_domain_bounce (Temporal::DomainBounceInfo&);
void set_time_domain (Temporal::TimeDomain);
class ChangeSuspender {
public:
@ -209,7 +215,7 @@ private:
Lock,
Cue,
Scene,
Domain
Domain,
};
void emit_signal (Signal);
@ -233,7 +239,7 @@ private:
};
/** A collection of session locations including unique dedicated locations (loop, punch, etc) */
class LIBARDOUR_API Locations : public SessionHandleRef, public PBD::StatefulDestructible
class LIBARDOUR_API Locations : public SessionHandleRef, public PBD::StatefulDestructible, public Temporal::TimeDomainProvider, public Temporal::TimeDomainSwapper
{
public:
typedef std::list<Location *> LocationList;
@ -303,8 +309,11 @@ public:
void find_all_between (timepos_t const & start, timepos_t const & end, LocationList&, Location::Flags);
void globally_change_time_domain (Temporal::TimeDomain from, Temporal::TimeDomain to);
void change_time_domain (Temporal::TimeDomain from, Temporal::TimeDomain to);
void set_time_domain (Temporal::TimeDomain);
void start_domain_bounce (Temporal::DomainBounceInfo&);
void finish_domain_bounce (Temporal::DomainBounceInfo&);
void time_domain_changed ();
PBD::Signal1<void,Location*> current_changed;

View File

@ -26,7 +26,6 @@
#include <vector>
#include "temporal/beats.h"
#include "temporal/domainswap.h"
#include "temporal/range.h"
#include "pbd/string_convert.h"
@ -55,7 +54,7 @@ class ThawList;
template<typename T> class MidiRingBuffer;
class LIBARDOUR_API MidiRegion : public Region, public Temporal::TimeDomainSwapper
class LIBARDOUR_API MidiRegion : public Region
{
public:
~MidiRegion();
@ -117,8 +116,8 @@ class LIBARDOUR_API MidiRegion : public Region, public Temporal::TimeDomainSwapp
timecnt_t const & read_length,
MidiChannelFilter* filter) const;
void globally_change_time_domain (Temporal::TimeDomain from, Temporal::TimeDomain to);
void swap_domain (Temporal::TimeDomain, Temporal::TimeDomain);
void start_domain_bounce (Temporal::DomainBounceInfo&);
void finish_domain_bounce (Temporal::DomainBounceInfo&);
protected:

View File

@ -76,6 +76,9 @@ public:
bool has_state() const { return _has_state; }
void start_domain_bounce (Temporal::DomainBounceInfo&);
void finish_domain_bounce (Temporal::DomainBounceInfo&);
protected:
virtual XMLNode& state () const;

View File

@ -301,7 +301,8 @@ public:
void set_capture_insertion_in_progress (bool yn);
void time_domain_changed ();
void globally_change_time_domain (Temporal::TimeDomain from, Temporal::TimeDomain to);
void start_domain_bounce (Temporal::DomainBounceInfo&);
void finish_domain_bounce (Temporal::DomainBounceInfo&);
protected:
friend class Session;

View File

@ -29,6 +29,7 @@
#include <boost/utility.hpp>
#include "temporal/domain_swap.h"
#include "temporal/timeline.h"
#include "temporal/range.h"
@ -96,6 +97,7 @@ class LIBARDOUR_API Region
, public std::enable_shared_from_this<Region>
, public Trimmable
, public Movable
, public Temporal::TimeDomainSwapper
{
public:
typedef std::vector<std::shared_ptr<Source> > SourceList;
@ -115,8 +117,8 @@ public:
const DataType& data_type () const { return _type; }
Temporal::TimeDomain time_domain() const;
virtual void globally_change_time_domain (Temporal::TimeDomain from, Temporal::TimeDomain to);
virtual void change_time_domain (Temporal::TimeDomain from, Temporal::TimeDomain to);
void start_domain_bounce (Temporal::DomainBounceInfo&);
void finish_domain_bounce (Temporal::DomainBounceInfo&);
/** How the region parameters play together:
*
@ -386,7 +388,7 @@ public:
/* automation */
virtual std::shared_ptr<Evoral::Control>
control (const Evoral::Parameter& id, bool create=false) = 0;
control (const Evoral::Parameter& id, bool create=false) = 0;
virtual std::shared_ptr<const Evoral::Control>
control (const Evoral::Parameter& id) const = 0;

View File

@ -41,6 +41,7 @@
#include "pbd/controllable.h"
#include "pbd/destructible.h"
#include "temporal/domain_swap.h"
#include "temporal/types.h"
#include "ardour/ardour.h"
@ -612,7 +613,6 @@ public:
virtual void use_captured_sources (SourceList& srcs, CaptureInfos const &) {}
void globally_change_time_domain (Temporal::TimeDomain from, Temporal::TimeDomain to);
protected:
friend class Session;

View File

@ -1387,7 +1387,8 @@ public:
bool bang_trigger_at(int32_t route_index, int32_t row_index);
bool unbang_trigger_at(int32_t route_index, int32_t row_index);
PBD::Command* globally_change_time_domain (Temporal::TimeDomain from, Temporal::TimeDomain to);
void start_domain_bounce (Temporal::DomainBounceInfo&);
void finish_domain_bounce (Temporal::DomainBounceInfo&);
protected:
friend class AudioEngine;

View File

@ -70,7 +70,8 @@ public:
std::vector<std::shared_ptr<Playlist> > get_unused () const;
uint32_t n_playlists() const;
void globally_change_time_domain (Temporal::TimeDomain from, Temporal::TimeDomain to);
void start_domain_bounce (Temporal::DomainBounceInfo&);
void finish_domain_bounce (Temporal::DomainBounceInfo&);
private:
friend class Session;

View File

@ -743,3 +743,13 @@ Automatable::find_prev_ac_event (std::shared_ptr<AutomationControl> c, timepos_t
++i;
}
}
void
Automatable::start_domain_bounce (Temporal::DomainBounceInfo& cmd)
{
}
void
Automatable::finish_domain_bounce (Temporal::DomainBounceInfo& cmd)
{
}

View File

@ -92,22 +92,8 @@ Location::Location (Session& s, timepos_t const & start, timepos_t const & end,
set_position_time_domain (_session.time_domain());
}
void
Location::set_position_time_domain (TimeDomain domain)
{
if (_start.time_domain() == domain) {
return;
}
_start.set_time_domain (domain);
_end.set_time_domain (domain);
emit_signal (Domain); /* EMIT SIGNAL */
}
Location::Location (const Location& other)
: SessionHandleRef (other._session)
, StatefulDestructible()
, _name (other._name)
, _start (other._start)
, _end (other._end)
@ -253,6 +239,26 @@ Location::actually_emit_signal (Signal s)
}
}
void
Location::set_position_time_domain (TimeDomain domain)
{
if (_start.time_domain() == domain) {
return;
}
_start.set_time_domain (domain);
_end.set_time_domain (domain);
// emit_signal (Domain); /* EMIT SIGNAL */
}
void
Location::set_time_domain (TimeDomain domain)
{
set_position_time_domain (domain);
}
/** Set location name */
void
Location::set_name (const std::string& str)
@ -777,32 +783,53 @@ Location::set_scene_change (std::shared_ptr<SceneChange> sc)
}
void
Location::globally_change_time_domain (Temporal::TimeDomain from, Temporal::TimeDomain to)
Location::start_domain_bounce (Temporal::DomainBounceInfo& cmd)
{
assert (domain_swap);
if (_start.time_domain() == from) {
_start.set_time_domain (to);
_end.set_time_domain (to);
domain_swap->add (_start);
domain_swap->add (_end);
if (_start.time_domain() == cmd.to) {
/* has the right domain to begin with */
return;
}
timepos_t s (_start);
timepos_t e (_end);
s.set_time_domain (cmd.to);
e.set_time_domain (cmd.to);
cmd.positions.insert (std::make_pair (&_start, s));
cmd.positions.insert (std::make_pair (&_end, e));
}
void
Location::change_time_domain (Temporal::TimeDomain from, Temporal::TimeDomain to)
Location::finish_domain_bounce (Temporal::DomainBounceInfo& cmd)
{
if (_start.time_domain() == from) {
set_position_time_domain (to);
if (_start.time_domain() == cmd.to) {
/* had the right domain to begin with */
return;
}
TimeDomainPosChanges::iterator tpc;
timepos_t s;
timepos_t e;
tpc = cmd.positions.find (&_start);
assert (tpc != cmd.positions.end());
s = tpc->second;
s.set_time_domain (cmd.from);
tpc = cmd.positions.find (&_end);
assert (tpc != cmd.positions.end());
e = tpc->second;
e.set_time_domain (cmd.from);
set (s, e);
}
/*---------------------------------------------------------------------- */
Locations::Locations (Session& s)
: SessionHandleRef (s)
, Temporal::TimeDomainProvider (s, false) /* session is our parent */
{
current_location = 0;
}
@ -1890,21 +1917,28 @@ Locations::clear_cue_markers (samplepos_t start, samplepos_t end)
}
void
Locations::globally_change_time_domain (Temporal::TimeDomain from, Temporal::TimeDomain to)
Locations::start_domain_bounce (Temporal::DomainBounceInfo& cmd)
{
Glib::Threads::RWLock::WriterLock lm (_lock);
for (auto & l : locations) {
l->globally_change_time_domain (from, to);
}
for (auto & l : locations) {
l->start_domain_bounce (cmd);
}
}
void
Locations::change_time_domain (Temporal::TimeDomain from, Temporal::TimeDomain to)
Locations::finish_domain_bounce (Temporal::DomainBounceInfo& cmd)
{
for (auto & l : locations) {
l->finish_domain_bounce (cmd);
}
}
void
Locations::time_domain_changed ()
{
Glib::Threads::RWLock::WriterLock lm (_lock);
for (auto & l : locations) {
l->change_time_domain (from, to);
l->set_time_domain (time_domain());
}
}

View File

@ -1793,18 +1793,17 @@ MidiModel::create_mapping_stash (Temporal::Beats const & src_pos_offset)
Event<Beats>& off (n->off_event());
audio_time = tmap->superclock_at (src_pos_offset + off.time());
tempo_mapping_stash.insert (std::make_pair (&off, audio_time));
}
for (auto const & s : sysexes()) {
superclock_t audio_time = tmap->superclock_at (src_pos_offset + s->time());
tempo_mapping_stash.insert (std::make_pair ((void*)s.get(), audio_time));
tempo_mapping_stash.insert (std::make_pair (s.get(), audio_time));
}
for (uint8_t chan = 0; chan < 16; ++chan) {
for (auto const & p : pitches(chan)) {
superclock_t audio_time = tmap->superclock_at (src_pos_offset + p->time());
tempo_mapping_stash.insert (std::make_pair ((void*) &p, audio_time));
tempo_mapping_stash.insert (std::make_pair (p.get(), audio_time));
}
}
@ -1827,6 +1826,7 @@ MidiModel::rebuild_from_mapping_stash (Temporal::Beats const & src_pos_offset)
}
TempoMap::SharedPtr tmap (TempoMap::use());
NoteDiffCommand* note_cmd = new_note_diff_command (_("conform to tempo map"));
for (auto & n : notes()) {
@ -1836,17 +1836,21 @@ MidiModel::rebuild_from_mapping_stash (Temporal::Beats const & src_pos_offset)
TempoMappingStash::iterator tms (tempo_mapping_stash.find (&on));
assert (tms != tempo_mapping_stash.end());
Beats beat_time (tmap->quarters_at_superclock (tms->second) - src_pos_offset);
on.set_time (beat_time);
note_cmd->change (n, NoteDiffCommand::StartTime, beat_time);
tms = tempo_mapping_stash.find (&off);
assert (tms != tempo_mapping_stash.end());
beat_time = tmap->quarters_at_superclock (tms->second) - src_pos_offset;
off.set_time (beat_time);
note_cmd->change (n, NoteDiffCommand::Length, beat_time);
}
apply_diff_command_as_subcommand (_midi_source.session(), note_cmd);
for (auto & s : sysexes()) {
TempoMappingStash::iterator tms (tempo_mapping_stash.find ((void*) &s));
TempoMappingStash::iterator tms (tempo_mapping_stash.find (s.get()));
assert (tms != tempo_mapping_stash.end());
Beats beat_time (tmap->quarters_at_superclock (tms->second) - src_pos_offset);
s->set_time (beat_time);
@ -1854,7 +1858,7 @@ MidiModel::rebuild_from_mapping_stash (Temporal::Beats const & src_pos_offset)
for (uint8_t chan = 0; chan < 16; ++chan) {
for (auto & p : pitches(chan)) {
TempoMappingStash::iterator tms (tempo_mapping_stash.find ((void*) &p));
TempoMappingStash::iterator tms (tempo_mapping_stash.find (p.get()));
assert (tms != tempo_mapping_stash.end());
Beats beat_time (tmap->quarters_at_superclock (tms->second) - src_pos_offset);
p->set_time (beat_time);

View File

@ -614,23 +614,24 @@ MidiRegion::merge (std::shared_ptr<MidiRegion const> other_region)
}
void
MidiRegion::swap_domain (Temporal::TimeDomain from, Temporal::TimeDomain to)
MidiRegion::start_domain_bounce (Temporal::DomainBounceInfo& cmd)
{
if (from == Temporal::BeatTime) {
model()->create_mapping_stash (source_position().beats());
} else {
model()->rebuild_from_mapping_stash (source_position().beats());
/* Deal with the region position & length */
_model_changed_connection.disconnect ();
model()->ContentsChanged ();
model()->ContentsChanged.connect_same_thread (_model_changed_connection, boost::bind (&MidiRegion::model_contents_changed, this));
Region::start_domain_bounce (cmd);
if (cmd.from == Temporal::BeatTime) {
model()->create_mapping_stash (source_position().beats());
}
}
void
MidiRegion::globally_change_time_domain (Temporal::TimeDomain from, Temporal::TimeDomain to)
MidiRegion::finish_domain_bounce (Temporal::DomainBounceInfo& cmd)
{
Region::globally_change_time_domain (from, to);
swap_domain (from, to);
Temporal::domain_swap->add (*this);
Region::finish_domain_bounce (cmd);
model()->rebuild_from_mapping_stash (source_position().beats());
_model_changed_connection.disconnect ();
model()->ContentsChanged ();
model()->ContentsChanged.connect_same_thread (_model_changed_connection, boost::bind (&MidiRegion::model_contents_changed, this));
}

View File

@ -266,3 +266,14 @@ Pannable::set_state (const XMLNode& root, int version)
return 0;
}
void
Pannable::start_domain_bounce (Temporal::DomainBounceInfo&)
{
}
void
Pannable::finish_domain_bounce (Temporal::DomainBounceInfo&)
{
}

View File

@ -3530,17 +3530,38 @@ Playlist::rdiff_and_add_command (Session* session)
}
void
Playlist::globally_change_time_domain (Temporal::TimeDomain from, Temporal::TimeDomain to)
Playlist::start_domain_bounce (Temporal::DomainBounceInfo& cmd)
{
RegionReadLock rlock (this);
for (auto & region : regions) {
region->globally_change_time_domain (from, to);
region->start_domain_bounce (cmd);
}
}
void
Playlist::finish_domain_bounce (Temporal::DomainBounceInfo& cmd)
{
ThawList thawlist;
clear_changes ();
{
RegionWriteLock rlock (this);
for (auto & region : regions) {
thawlist.add (region);
region->finish_domain_bounce (cmd);
}
}
thawlist.release ();
rdiff_and_add_command (&_session);
}
void
Playlist::time_domain_changed ()
{
#if 0
using namespace Temporal;
TimeDomainProvider::time_domain_changed ();
@ -3549,8 +3570,8 @@ Playlist::time_domain_changed ()
Temporal::TimeDomain from = (to == AudioTime ? BeatTime : AudioTime);
for (auto & region : regions) {
region->change_time_domain (from, to);
region->swap_time_domain (from, to);
}
#endif
}

View File

@ -2270,27 +2270,39 @@ Region::time_domain() const
}
void
Region::globally_change_time_domain (Temporal::TimeDomain from, Temporal::TimeDomain to)
Region::start_domain_bounce (Temporal::DomainBounceInfo& cmd)
{
assert (Temporal::domain_swap);
if (locked()) {
return;
}
/* recall that the _length member is a timecnt_t, and so holds both
* position *and* length.
*/
if (_length.val().time_domain() == from) {
timecnt_t& l (_length.non_const_val());
l.set_time_domain (to);
Temporal::domain_swap->add (l);
if (_length.val().time_domain() != cmd.from) {
return;
}
timecnt_t& l (_length.non_const_val());
timecnt_t saved (l);
saved.set_time_domain (cmd.to);
cmd.counts.insert (std::make_pair (&l, saved));
}
void
Region::change_time_domain (Temporal::TimeDomain from, Temporal::TimeDomain to)
Region::finish_domain_bounce (Temporal::DomainBounceInfo& cmd)
{
std::cerr << name() << " change td to " << to << std::endl;
if (_length.val().time_domain() == from) {
timecnt_t& l (_length.non_const_val());
l.set_time_domain (to);
}
clear_changes ();
Temporal::TimeDomainCntChanges::iterator tc = cmd.counts.find (&_length.non_const_val());
assert (tc != cmd.counts.end());
/* switch domains back (but with modified TempoMap, presumably */
tc->second.set_time_domain (cmd.from);
_length = tc->second;
send_change (Properties::length);
}

View File

@ -6349,8 +6349,3 @@ Route::tempo_map_changed ()
_triggerbox->tempo_map_changed ();
}
}
void
Route::globally_change_time_domain (Temporal::TimeDomain from, Temporal::TimeDomain to)
{
}

View File

@ -7787,15 +7787,3 @@ Session::foreach_route (void (Route::*method)())
}
}
void
Session::time_domain_changed ()
{
using namespace Temporal;
TimeDomainProvider::time_domain_changed ();
Temporal::TimeDomain to = time_domain();
Temporal::TimeDomain from = (to == AudioTime ? BeatTime : AudioTime);
_locations->change_time_domain (from, to);
}

View File

@ -689,11 +689,31 @@ SessionPlaylists::foreach (boost::function<void(std::shared_ptr<const Playlist>)
}
void
SessionPlaylists::globally_change_time_domain (Temporal::TimeDomain from, Temporal::TimeDomain to)
SessionPlaylists::start_domain_bounce (Temporal::DomainBounceInfo& cmd)
{
Glib::Threads::Mutex::Lock lm (lock);
for (auto & pl : playlists) {
pl->globally_change_time_domain (from, to);
pl->start_domain_bounce (cmd);
}
}
void
SessionPlaylists::finish_domain_bounce (Temporal::DomainBounceInfo& cmd)
{
/* We cannot hold the playlist lock while finishing a domain bounce
*/
std::vector<std::shared_ptr<Playlist> > copy;
{
Glib::Threads::Mutex::Lock lm (lock);
for (auto & pl : playlists) {
copy.push_back (pl);
}
}
for (auto & pl : copy) {
pl->finish_domain_bounce (cmd);
}
}

View File

@ -3346,6 +3346,7 @@ Session::add_stateful_diff_command (std::shared_ptr<PBD::StatefulDestructible> s
void
Session::begin_reversible_command (const string& name)
{
std::cerr << "begin REV-C [" << name << "]\n";
begin_reversible_command (g_quark_from_string (name.c_str ()));
}
@ -3395,6 +3396,7 @@ Session::abort_reversible_command ()
if (_current_trans != 0) {
DEBUG_UNDO_HISTORY (
string_compose ("Abort Reversible Command: %1", _current_trans->name ()));
std::cerr << "abort REV-C [" << _current_trans->name() << "]\n";
_current_trans->clear();
delete _current_trans;
_current_trans = 0;
@ -3421,6 +3423,7 @@ Session::commit_reversible_command (Command *cmd)
return;
}
std::cerr << "commit REV-C [" << _current_trans->name() << "]\n";
struct timeval now;
if (cmd) {
@ -3460,6 +3463,8 @@ Session::commit_reversible_command (Command *cmd)
gettimeofday (&now, 0);
_current_trans->set_timestamp (now);
std::cerr << "Add command with " << _current_trans->size() << std::endl;
_history.add (_current_trans);
_current_trans = 0;
}

View File

@ -299,21 +299,42 @@ Session::any_duration_to_samples (samplepos_t position, AnyTime const & duration
return duration.samples;
}
PBD::Command*
Session::globally_change_time_domain (Temporal::TimeDomain from, Temporal::TimeDomain to)
void
Session::start_domain_bounce (Temporal::DomainBounceInfo& cmd)
{
PBD::Command* undo_command = new Temporal::TimeDomainCommand (from, to);
{
std::shared_ptr<RouteList const> rl (routes.reader());
for (auto const& r : *rl) {
r->globally_change_time_domain (from, to);
r->start_domain_bounce (cmd);
}
}
_playlists->globally_change_time_domain (from, to);
_locations->globally_change_time_domain (from, to);
return undo_command;
_playlists->start_domain_bounce(cmd);
_locations->start_domain_bounce (cmd);
}
void
Session::finish_domain_bounce (Temporal::DomainBounceInfo& cmd)
{
{
std::shared_ptr<RouteList const> rl (routes.reader());
for (auto const& r : *rl) {
r->finish_domain_bounce (cmd);
}
}
_playlists->finish_domain_bounce (cmd);
_locations->finish_domain_bounce (cmd);
}
void
Session::time_domain_changed ()
{
TimeDomainProvider::time_domain_changed ();
// _playlists->set_time_domain (time_domain());
// _locations->set_time_domain (time_domain());
}

View File

@ -60,6 +60,8 @@ public:
void add_command (PBD::Command* const);
void remove_command (PBD::Command* const);
std::list<PBD::Command*>::size_type size() const { return actions.size(); }
void operator() ();
void undo ();
void redo ();

View File

@ -16,39 +16,7 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "temporal/domainswap.h"
#include "temporal/domain_swap.h"
using namespace Temporal;
void
TimeDomainCommand::add (TimeDomainSwapper& tds)
{
tds.DropReferences.connect_same_thread (tds_connections, boost::bind (&TimeDomainCommand::going_away, this, &tds));
swappers.insert (&tds);
}
void
TimeDomainCommand::going_away (TimeDomainSwapper* tds)
{
Swappers::iterator i = swappers.find (tds);
if (i != swappers.end()) {
swappers.erase (i);
}
}
void
TimeDomainCommand::operator() ()
{
for (auto & swapper : swappers) {
swapper->swap_domain (from, to);
}
}
void
TimeDomainCommand::undo ()
{
for (auto & swapper : swappers) {
swapper->swap_domain (to, from);
}
}

View File

@ -4864,49 +4864,6 @@ TempoCommand::operator() ()
TempoMap::update (map);
}
DomainSwapInformation* Temporal::domain_swap (0);
DomainSwapInformation*
DomainSwapInformation::start(TimeDomain prev)
{
TEMPO_MAP_ASSERT (!domain_swap);
domain_swap = new DomainSwapInformation (prev);
return domain_swap;
}
DomainSwapInformation::~DomainSwapInformation ()
{
TEMPO_MAP_ASSERT (this == domain_swap);
undo ();
domain_swap = 0;
}
void
DomainSwapInformation::clear ()
{
counts.clear ();
positions.clear ();
}
void
DomainSwapInformation::undo ()
{
std::cerr << "DSI::undo on " << counts.size() << " lengths and " << positions.size() << " positions\n";
for (auto & c : counts) {
c->set_time_domain (previous);
}
for (auto & p : positions) {
p->set_time_domain (previous);
}
for (auto & tt : time_things) {
tt->swap_domain (previous == AudioTime ? BeatTime : AudioTime, previous);
}
clear ();
}
TempoMapCutBuffer::TempoMapCutBuffer (timecnt_t const & dur)
: _start_tempo (nullptr)
, _end_tempo (nullptr)

View File

@ -30,56 +30,38 @@
namespace Temporal {
typedef std::map<timepos_t*,timepos_t> TimeDomainPosChanges;
typedef std::map<timecnt_t*,timecnt_t> TimeDomainCntChanges;
struct LIBTEMPORAL_API DomainBounceInfo;
struct LIBTEMPORAL_API TimeDomainSwapper : public virtual PBD::Destructible {
virtual ~TimeDomainSwapper() {}
virtual void swap_domain (Temporal::TimeDomain from, Temporal::TimeDomain to) = 0;
};
struct LIBTEMPORAL_API TimeDomainCommand : public PBD::Command {
public:
TimeDomainCommand (TimeDomain f, TimeDomain t) : from (f), to (t) {}
void add (TimeDomainSwapper&);
void operator() ();
void undo ();
private:
TimeDomain from;
TimeDomain to;
typedef std::set<TimeDomainSwapper*> Swappers;
Swappers swappers;
PBD::ScopedConnectionList tds_connections;
void going_away (TimeDomainSwapper*);
virtual ~TimeDomainSwapper() {}
virtual void start_domain_bounce (DomainBounceInfo&) = 0;
virtual void finish_domain_bounce (DomainBounceInfo&) = 0;
};
class LIBTEMPORAL_API DomainSwapInformation {
public:
static DomainSwapInformation* start (TimeDomain prev);
/* A DomainBounceInfo functions in two roles:
*
* 1. as part of an UndoTransaction reflecting actions taken by a user that
* modified time domains of one or more objects.
*
* 2. as a standalone object used during temporary domain swaps that records
* (perhaps opaquely) what was changed and provides a way to revert it.
*/
~DomainSwapInformation ();
struct LIBTEMPORAL_API DomainBounceInfo
{
DomainBounceInfo (TimeDomain f, TimeDomain t) : from (f), to (t) {}
void add (timecnt_t& t) { counts.push_back (&t); }
void add (timepos_t& p) { positions.push_back (&p); }
void add (TimeDomainSwapper& tt) { time_things.push_back (&tt); }
void clear ();
const TimeDomain from;
const TimeDomain to;
private:
DomainSwapInformation (TimeDomain prev) : previous (prev) {}
std::vector<timecnt_t*> counts;
std::vector<timepos_t*> positions;
std::vector<TimeDomainSwapper*> time_things;
TimeDomain previous;
void undo ();
TimeDomainPosChanges positions;
TimeDomainCntChanges counts;
};
extern LIBTEMPORAL_API DomainSwapInformation* domain_swap;
}
#endif /* __tmeporal_domain_swap_h__ */

View File

@ -42,7 +42,7 @@
#include "temporal/beats.h"
#include "temporal/bbt_argument.h"
#include "temporal/bbt_time.h"
#include "temporal/domainswap.h"
#include "temporal/domain_swap.h"
#include "temporal/superclock.h"
#include "temporal/timeline.h"
#include "temporal/types.h"

View File

@ -28,7 +28,7 @@ temporal_sources = [
'debug.cc',
'bbt_time.cc',
'beats.cc',
'domainswap.cc',
'domain_swap.cc',
'enums.cc',
'range.cc',
'superclock.cc',