extend MidiModel and MIDITrigger in preparation for edit-change handling
This commit is contained in:
@@ -48,6 +48,7 @@ namespace ARDOUR {
|
||||
|
||||
class Session;
|
||||
class MidiSource;
|
||||
class MidiStateTracker;
|
||||
|
||||
/** This is a higher level (than MidiBuffer) model of MIDI data, with separate
|
||||
* representations for notes (instead of just unassociated note on/off events)
|
||||
@@ -61,6 +62,7 @@ public:
|
||||
typedef Temporal::Beats TimeType;
|
||||
|
||||
MidiModel (MidiSource&);
|
||||
MidiModel (MidiModel const & other, MidiSource&);
|
||||
|
||||
class LIBARDOUR_API DiffCommand : public PBD::Command {
|
||||
public:
|
||||
@@ -324,6 +326,8 @@ public:
|
||||
void insert_silence_at_start (TimeType);
|
||||
void transpose (NoteDiffCommand *, const NotePtr, int);
|
||||
|
||||
void track_state (timepos_t const & when, MidiStateTracker&) const;
|
||||
|
||||
protected:
|
||||
int resolve_overlaps_unlocked (const NotePtr, void* arg = 0);
|
||||
|
||||
|
||||
@@ -580,6 +580,8 @@ class LIBARDOUR_API MIDITrigger : public Trigger {
|
||||
return midi_run<true> (bufs, start_sample, end_sample, start, end, nframes, dest_offset, bpm, quantize_offset);
|
||||
}
|
||||
|
||||
void swap_model (std::shared_ptr<ARDOUR::MidiModel>, ARDOUR::MidiModel::DiffCommand*);
|
||||
|
||||
void set_start (timepos_t const &);
|
||||
void set_end (timepos_t const &);
|
||||
void set_legato_offset (timepos_t const &);
|
||||
@@ -657,6 +659,16 @@ class LIBARDOUR_API MIDITrigger : public Trigger {
|
||||
int load_data (std::shared_ptr<MidiRegion>);
|
||||
void compute_and_set_length ();
|
||||
void _startup (BufferSet&, pframes_t dest_offset, Temporal::BBT_Offset const &);
|
||||
|
||||
struct ModelSwap {
|
||||
std::shared_ptr<ARDOUR::MidiModel> model;
|
||||
ARDOUR::MidiModel::DiffCommand* cmd;
|
||||
|
||||
ModelSwap (std::shared_ptr<ARDOUR::MidiModel> m, ARDOUR::MidiModel::DiffCommand* c)
|
||||
: model (m), cmd (c) {}
|
||||
};
|
||||
|
||||
std::atomic<ModelSwap*> model_swap;
|
||||
};
|
||||
|
||||
class LIBARDOUR_API TriggerBoxThread
|
||||
|
||||
@@ -66,6 +66,14 @@ MidiModel::MidiModel (MidiSource& s)
|
||||
_midi_source.AutomationStateChanged.connect_same_thread (_midi_source_connections, boost::bind (&MidiModel::source_automation_state_changed, this, _1, _2));
|
||||
}
|
||||
|
||||
MidiModel::MidiModel (MidiModel const & other, MidiSource & s)
|
||||
: AutomatableSequence<TimeType> (other)
|
||||
, _midi_source (s)
|
||||
{
|
||||
_midi_source.InterpolationChanged.connect_same_thread (_midi_source_connections, boost::bind (&MidiModel::source_interpolation_changed, this, _1, _2));
|
||||
_midi_source.AutomationStateChanged.connect_same_thread (_midi_source_connections, boost::bind (&MidiModel::source_automation_state_changed, this, _1, _2));
|
||||
}
|
||||
|
||||
MidiModel::NoteDiffCommand*
|
||||
MidiModel::new_note_diff_command (const string& name)
|
||||
{
|
||||
@@ -1424,7 +1432,7 @@ MidiModel::find_sysex (Evoral::event_id_t sysex_id)
|
||||
MidiModel::WriteLock
|
||||
MidiModel::edit_lock()
|
||||
{
|
||||
Source::WriterLock* source_lock = 0;
|
||||
Source::WriterLock* source_lock = nullptr;
|
||||
|
||||
/* Take source lock and invalidate iterator to release its lock on model.
|
||||
* Add currently active notes to _active_notes so we can restore them
|
||||
@@ -1866,3 +1874,11 @@ MidiModel::rebuild_from_mapping_stash (Temporal::Beats const & src_pos_offset)
|
||||
|
||||
tempo_mapping_stash.clear ();
|
||||
}
|
||||
|
||||
void
|
||||
MidiModel::track_state (timepos_t const & when, MidiStateTracker& mst) const
|
||||
{
|
||||
for (auto const & ev : *this) {
|
||||
mst.track (ev.buffer());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -497,6 +497,7 @@ void
|
||||
MidiSource::set_model (const WriterLock& lock, std::shared_ptr<MidiModel> m)
|
||||
{
|
||||
_model = m;
|
||||
std::cerr << "Source " << name() << " switched to model " << _model << std::endl;
|
||||
invalidate(lock);
|
||||
ModelChanged (); /* EMIT SIGNAL */
|
||||
}
|
||||
|
||||
@@ -2205,6 +2205,7 @@ MIDITrigger::MIDITrigger (uint32_t n, TriggerBox& b)
|
||||
, pending_rt_midibuffer (nullptr)
|
||||
, old_rt_midibuffer (nullptr)
|
||||
, map_change (false)
|
||||
, model_swap (nullptr)
|
||||
{
|
||||
_channel_map.assign (16, -1);
|
||||
}
|
||||
@@ -2213,6 +2214,14 @@ MIDITrigger::~MIDITrigger ()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
MIDITrigger::check_edit_swap (bool playing)
|
||||
{
|
||||
if (model_swap != nullptr) {
|
||||
std::cerr << "EDIT!\n";
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MIDITrigger::set_used_channels (Evoral::SMF::UsedChannels used)
|
||||
{
|
||||
@@ -2779,6 +2788,13 @@ MIDITrigger::tempo_map_changed ()
|
||||
map_change = true;
|
||||
}
|
||||
|
||||
void
|
||||
MIDITrigger::swap_model (std::shared_ptr<ARDOUR::MidiModel> model, ARDOUR::MidiModel::DiffCommand* cmd)
|
||||
{
|
||||
ModelSwap* ms = new ModelSwap (model, cmd);
|
||||
model_swap = ms;
|
||||
}
|
||||
|
||||
template<bool in_process_context>
|
||||
pframes_t
|
||||
MIDITrigger::midi_run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sample,
|
||||
@@ -2787,12 +2803,15 @@ MIDITrigger::midi_run (BufferSet& bufs, samplepos_t start_sample, samplepos_t en
|
||||
{
|
||||
assert (rt_midibuffer);
|
||||
|
||||
MidiBuffer* mb (in_process_context? &bufs.get_midi (0) : 0);
|
||||
MidiBuffer* mb (in_process_context? &bufs.get_midi (0) : nullptr);
|
||||
typedef Evoral::Event<MidiModel::TimeType> MidiEvent;
|
||||
const timepos_t region_start_time = _region->start();
|
||||
const Temporal::Beats region_start = region_start_time.beats();
|
||||
Temporal::TempoMap::SharedPtr tmap (Temporal::TempoMap::use());
|
||||
|
||||
std::shared_ptr<MidiRegion> mr = std::dynamic_pointer_cast<MidiRegion> (_region);
|
||||
assert (mr);
|
||||
|
||||
last_event_samples = end_sample;
|
||||
|
||||
/* see if we're going to start or stop or retrigger in this run() call */
|
||||
@@ -3145,7 +3164,7 @@ TriggerBox::send_property_change (PBD::PropertyChange pc)
|
||||
|
||||
TriggerBox::TriggerBox (Session& s, DataType dt)
|
||||
: Processor (s, _("TriggerBox"), Temporal::TimeDomainProvider (Temporal::BeatTime))
|
||||
, tracker (dt == DataType::MIDI ? new MidiStateTracker : 0)
|
||||
, tracker (dt == DataType::MIDI ? new MidiStateTracker : nullptr)
|
||||
, _data_type (dt)
|
||||
, _order (-1)
|
||||
, explicit_queue (64)
|
||||
@@ -4830,6 +4849,10 @@ TriggerBox::process_requests (BufferSet& bufs)
|
||||
{
|
||||
Request* r;
|
||||
|
||||
for (uint64_t n = 0; n < all_triggers.size(); ++n) {
|
||||
all_triggers[n]->check_edit_swap (_currently_playing == all_triggers[n]);
|
||||
}
|
||||
|
||||
while (requests.read (&r, 1) == 1) {
|
||||
process_request (bufs, r);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user