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 */ /* automation */
std::shared_ptr<Evoral::Control> 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); return _automatable.control(id, create);
} }
virtual std::shared_ptr<const Evoral::Control> virtual std::shared_ptr<const Evoral::Control>
control(const Evoral::Parameter& id) const { control(const Evoral::Parameter& id) const {
return _automatable.control(id); return _automatable.control(id);
} }

View file

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

View file

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

View file

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

View file

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

View file

@ -301,7 +301,8 @@ public:
void set_capture_insertion_in_progress (bool yn); void set_capture_insertion_in_progress (bool yn);
void time_domain_changed (); 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: protected:
friend class Session; friend class Session;

View file

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

View file

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

View file

@ -1387,7 +1387,8 @@ public:
bool bang_trigger_at(int32_t route_index, int32_t row_index); bool bang_trigger_at(int32_t route_index, int32_t row_index);
bool unbang_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: protected:
friend class AudioEngine; friend class AudioEngine;

View file

@ -70,7 +70,8 @@ public:
std::vector<std::shared_ptr<Playlist> > get_unused () const; std::vector<std::shared_ptr<Playlist> > get_unused () const;
uint32_t n_playlists() 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: private:
friend class Session; friend class Session;

View file

@ -743,3 +743,13 @@ Automatable::find_prev_ac_event (std::shared_ptr<AutomationControl> c, timepos_t
++i; ++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()); 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) Location::Location (const Location& other)
: SessionHandleRef (other._session) : SessionHandleRef (other._session)
, StatefulDestructible()
, _name (other._name) , _name (other._name)
, _start (other._start) , _start (other._start)
, _end (other._end) , _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 */ /** Set location name */
void void
Location::set_name (const std::string& str) Location::set_name (const std::string& str)
@ -777,32 +783,53 @@ Location::set_scene_change (std::shared_ptr<SceneChange> sc)
} }
void 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() == cmd.to) {
/* has the right domain to begin with */
if (_start.time_domain() == from) { return;
_start.set_time_domain (to);
_end.set_time_domain (to);
domain_swap->add (_start);
domain_swap->add (_end);
} }
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 void
Location::change_time_domain (Temporal::TimeDomain from, Temporal::TimeDomain to) Location::finish_domain_bounce (Temporal::DomainBounceInfo& cmd)
{ {
if (_start.time_domain() == from) { if (_start.time_domain() == cmd.to) {
set_position_time_domain (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) Locations::Locations (Session& s)
: SessionHandleRef (s) : SessionHandleRef (s)
, Temporal::TimeDomainProvider (s, false) /* session is our parent */
{ {
current_location = 0; current_location = 0;
} }
@ -1890,21 +1917,28 @@ Locations::clear_cue_markers (samplepos_t start, samplepos_t end)
} }
void 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); 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 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); Glib::Threads::RWLock::WriterLock lm (_lock);
for (auto & l : locations) { 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()); Event<Beats>& off (n->off_event());
audio_time = tmap->superclock_at (src_pos_offset + off.time()); audio_time = tmap->superclock_at (src_pos_offset + off.time());
tempo_mapping_stash.insert (std::make_pair (&off, audio_time)); tempo_mapping_stash.insert (std::make_pair (&off, audio_time));
} }
for (auto const & s : sysexes()) { for (auto const & s : sysexes()) {
superclock_t audio_time = tmap->superclock_at (src_pos_offset + s->time()); 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 (uint8_t chan = 0; chan < 16; ++chan) {
for (auto const & p : pitches(chan)) { for (auto const & p : pitches(chan)) {
superclock_t audio_time = tmap->superclock_at (src_pos_offset + p->time()); 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()); TempoMap::SharedPtr tmap (TempoMap::use());
NoteDiffCommand* note_cmd = new_note_diff_command (_("conform to tempo map"));
for (auto & n : notes()) { 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)); TempoMappingStash::iterator tms (tempo_mapping_stash.find (&on));
assert (tms != tempo_mapping_stash.end()); assert (tms != tempo_mapping_stash.end());
Beats beat_time (tmap->quarters_at_superclock (tms->second) - src_pos_offset); 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); tms = tempo_mapping_stash.find (&off);
assert (tms != tempo_mapping_stash.end()); assert (tms != tempo_mapping_stash.end());
beat_time = tmap->quarters_at_superclock (tms->second) - src_pos_offset; beat_time = tmap->quarters_at_superclock (tms->second) - src_pos_offset;
off.set_time (beat_time); 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()) { 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()); assert (tms != tempo_mapping_stash.end());
Beats beat_time (tmap->quarters_at_superclock (tms->second) - src_pos_offset); Beats beat_time (tmap->quarters_at_superclock (tms->second) - src_pos_offset);
s->set_time (beat_time); 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 (uint8_t chan = 0; chan < 16; ++chan) {
for (auto & p : pitches(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()); assert (tms != tempo_mapping_stash.end());
Beats beat_time (tmap->quarters_at_superclock (tms->second) - src_pos_offset); Beats beat_time (tmap->quarters_at_superclock (tms->second) - src_pos_offset);
p->set_time (beat_time); p->set_time (beat_time);

View file

@ -614,23 +614,24 @@ MidiRegion::merge (std::shared_ptr<MidiRegion const> other_region)
} }
void void
MidiRegion::swap_domain (Temporal::TimeDomain from, Temporal::TimeDomain to) MidiRegion::start_domain_bounce (Temporal::DomainBounceInfo& cmd)
{ {
if (from == Temporal::BeatTime) { /* Deal with the region position & length */
model()->create_mapping_stash (source_position().beats());
} else {
model()->rebuild_from_mapping_stash (source_position().beats());
_model_changed_connection.disconnect (); Region::start_domain_bounce (cmd);
model()->ContentsChanged (); if (cmd.from == Temporal::BeatTime) {
model()->ContentsChanged.connect_same_thread (_model_changed_connection, boost::bind (&MidiRegion::model_contents_changed, this)); model()->create_mapping_stash (source_position().beats());
} }
} }
void 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); Region::finish_domain_bounce (cmd);
swap_domain (from, to);
Temporal::domain_swap->add (*this); 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; 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 void
Playlist::globally_change_time_domain (Temporal::TimeDomain from, Temporal::TimeDomain to) Playlist::start_domain_bounce (Temporal::DomainBounceInfo& cmd)
{ {
RegionReadLock rlock (this); RegionReadLock rlock (this);
for (auto & region : regions) { 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 void
Playlist::time_domain_changed () Playlist::time_domain_changed ()
{ {
#if 0
using namespace Temporal; using namespace Temporal;
TimeDomainProvider::time_domain_changed (); TimeDomainProvider::time_domain_changed ();
@ -3549,8 +3570,8 @@ Playlist::time_domain_changed ()
Temporal::TimeDomain from = (to == AudioTime ? BeatTime : AudioTime); Temporal::TimeDomain from = (to == AudioTime ? BeatTime : AudioTime);
for (auto & region : regions) { 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 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 /* recall that the _length member is a timecnt_t, and so holds both
* position *and* length. * position *and* length.
*/ */
if (_length.val().time_domain() == from) { if (_length.val().time_domain() != cmd.from) {
timecnt_t& l (_length.non_const_val()); return;
l.set_time_domain (to);
Temporal::domain_swap->add (l);
} }
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 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; clear_changes ();
if (_length.val().time_domain() == from) {
timecnt_t& l (_length.non_const_val()); Temporal::TimeDomainCntChanges::iterator tc = cmd.counts.find (&_length.non_const_val());
l.set_time_domain (to); 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 (); _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 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); Glib::Threads::Mutex::Lock lm (lock);
for (auto & pl : playlists) { 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 void
Session::begin_reversible_command (const string& name) Session::begin_reversible_command (const string& name)
{ {
std::cerr << "begin REV-C [" << name << "]\n";
begin_reversible_command (g_quark_from_string (name.c_str ())); begin_reversible_command (g_quark_from_string (name.c_str ()));
} }
@ -3395,6 +3396,7 @@ Session::abort_reversible_command ()
if (_current_trans != 0) { if (_current_trans != 0) {
DEBUG_UNDO_HISTORY ( DEBUG_UNDO_HISTORY (
string_compose ("Abort Reversible Command: %1", _current_trans->name ())); string_compose ("Abort Reversible Command: %1", _current_trans->name ()));
std::cerr << "abort REV-C [" << _current_trans->name() << "]\n";
_current_trans->clear(); _current_trans->clear();
delete _current_trans; delete _current_trans;
_current_trans = 0; _current_trans = 0;
@ -3421,6 +3423,7 @@ Session::commit_reversible_command (Command *cmd)
return; return;
} }
std::cerr << "commit REV-C [" << _current_trans->name() << "]\n";
struct timeval now; struct timeval now;
if (cmd) { if (cmd) {
@ -3460,6 +3463,8 @@ Session::commit_reversible_command (Command *cmd)
gettimeofday (&now, 0); gettimeofday (&now, 0);
_current_trans->set_timestamp (now); _current_trans->set_timestamp (now);
std::cerr << "Add command with " << _current_trans->size() << std::endl;
_history.add (_current_trans); _history.add (_current_trans);
_current_trans = 0; _current_trans = 0;
} }

View file

@ -299,21 +299,42 @@ Session::any_duration_to_samples (samplepos_t position, AnyTime const & duration
return duration.samples; return duration.samples;
} }
PBD::Command* void
Session::globally_change_time_domain (Temporal::TimeDomain from, Temporal::TimeDomain to) Session::start_domain_bounce (Temporal::DomainBounceInfo& cmd)
{ {
PBD::Command* undo_command = new Temporal::TimeDomainCommand (from, to);
{ {
std::shared_ptr<RouteList const> rl (routes.reader()); std::shared_ptr<RouteList const> rl (routes.reader());
for (auto const& r : *rl) { for (auto const& r : *rl) {
r->globally_change_time_domain (from, to); r->start_domain_bounce (cmd);
} }
} }
_playlists->globally_change_time_domain (from, to); _playlists->start_domain_bounce(cmd);
_locations->globally_change_time_domain (from, to); _locations->start_domain_bounce (cmd);
return undo_command;
} }
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 add_command (PBD::Command* const);
void remove_command (PBD::Command* const); void remove_command (PBD::Command* const);
std::list<PBD::Command*>::size_type size() const { return actions.size(); }
void operator() (); void operator() ();
void undo (); void undo ();
void redo (); void redo ();

View file

@ -16,39 +16,7 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
#include "temporal/domainswap.h" #include "temporal/domain_swap.h"
using namespace Temporal; 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); 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) TempoMapCutBuffer::TempoMapCutBuffer (timecnt_t const & dur)
: _start_tempo (nullptr) : _start_tempo (nullptr)
, _end_tempo (nullptr) , _end_tempo (nullptr)

View file

@ -30,56 +30,38 @@
namespace Temporal { 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 { 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: public:
TimeDomainCommand (TimeDomain f, TimeDomain t) : from (f), to (t) {} virtual ~TimeDomainSwapper() {}
void add (TimeDomainSwapper&); virtual void start_domain_bounce (DomainBounceInfo&) = 0;
virtual void finish_domain_bounce (DomainBounceInfo&) = 0;
void operator() ();
void undo ();
private:
TimeDomain from;
TimeDomain to;
typedef std::set<TimeDomainSwapper*> Swappers;
Swappers swappers;
PBD::ScopedConnectionList tds_connections;
void going_away (TimeDomainSwapper*);
}; };
class LIBTEMPORAL_API DomainSwapInformation { /* A DomainBounceInfo functions in two roles:
public: *
static DomainSwapInformation* start (TimeDomain prev); * 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); } const TimeDomain from;
void add (timepos_t& p) { positions.push_back (&p); } const TimeDomain to;
void add (TimeDomainSwapper& tt) { time_things.push_back (&tt); }
void clear ();
private: TimeDomainPosChanges positions;
DomainSwapInformation (TimeDomain prev) : previous (prev) {} TimeDomainCntChanges counts;
std::vector<timecnt_t*> counts;
std::vector<timepos_t*> positions;
std::vector<TimeDomainSwapper*> time_things;
TimeDomain previous;
void undo ();
}; };
extern LIBTEMPORAL_API DomainSwapInformation* domain_swap;
} }
#endif /* __tmeporal_domain_swap_h__ */ #endif /* __tmeporal_domain_swap_h__ */

View file

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

View file

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