next iteration of changes to handle time domain bounces as undoable
This commit is contained in:
parent
5e3cdf285e
commit
076cb86912
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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&)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -6349,8 +6349,3 @@ Route::tempo_map_changed ()
|
|||
_triggerbox->tempo_map_changed ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Route::globally_change_time_domain (Temporal::TimeDomain from, Temporal::TimeDomain to)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
|
|
|
@ -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__ */
|
|
@ -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"
|
||||
|
|
|
@ -28,7 +28,7 @@ temporal_sources = [
|
|||
'debug.cc',
|
||||
'bbt_time.cc',
|
||||
'beats.cc',
|
||||
'domainswap.cc',
|
||||
'domain_swap.cc',
|
||||
'enums.cc',
|
||||
'range.cc',
|
||||
'superclock.cc',
|
||||
|
|
Loading…
Reference in New Issue