various changes to get MIDI clip recording to display the post-capture region
This commit is contained in:
parent
aa2fb8c1d4
commit
e11caf2dea
@ -494,20 +494,6 @@ MidiCueEditor::idle_data_captured ()
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
MidiCueEditor::set_box (std::shared_ptr<ARDOUR::TriggerBox> b)
|
||||
{
|
||||
capture_connections.drop_connections ();
|
||||
idle_update_queued.store (0);
|
||||
|
||||
if (b) {
|
||||
b->Captured.connect (capture_connections, invalidator (*this), std::bind (&MidiCueEditor::data_captured, this, _1), gui_context());
|
||||
/* Don't bind a shared_ptr<TriggerBox> within the lambda */
|
||||
TriggerBox* tb (b.get());
|
||||
b->RecEnableChanged.connect (capture_connections, invalidator (*this), [&, tb]() { box_rec_enable_change (*tb); }, gui_context());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MidiCueEditor::box_rec_enable_change (ARDOUR::TriggerBox const & b)
|
||||
{
|
||||
@ -528,61 +514,6 @@ MidiCueEditor::trigger_rec_enable_change (ARDOUR::Trigger const & t)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MidiCueEditor::set_track (std::shared_ptr<ARDOUR::MidiTrack> t)
|
||||
{
|
||||
_track = t;
|
||||
|
||||
view->set_track (t);
|
||||
|
||||
_update_connection.disconnect ();
|
||||
capture_connections.drop_connections ();
|
||||
|
||||
if (t) {
|
||||
set_box (t->triggerbox());
|
||||
_update_connection = Timers::rapid_connect (sigc::mem_fun (*this, &MidiCueEditor::maybe_update));
|
||||
_track->DropReferences.connect (track_connection, invalidator (*this), std::bind (&MidiCueEditor::set_track, this, nullptr), gui_context());
|
||||
} else {
|
||||
set_box (nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MidiCueEditor::set_region (std::shared_ptr<ARDOUR::MidiRegion> r)
|
||||
{
|
||||
if (!r) {
|
||||
view->set_region (nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
view->set_region (r);
|
||||
|
||||
/* Compute zoom level to show entire source plus some margin if possible */
|
||||
|
||||
Temporal::timecnt_t duration = Temporal::timecnt_t (r->midi_source()->length().beats());
|
||||
|
||||
bool provided = false;
|
||||
std::shared_ptr<Temporal::TempoMap> map;
|
||||
std::shared_ptr<SMFSource> smf (std::dynamic_pointer_cast<SMFSource> (r->midi_source()));
|
||||
|
||||
if (smf) {
|
||||
map = smf->tempo_map (provided);
|
||||
}
|
||||
|
||||
if (!provided) {
|
||||
map.reset (new Temporal::TempoMap (Temporal::Tempo (120, 4), Temporal::Meter (4, 4)));
|
||||
}
|
||||
|
||||
{
|
||||
EditingContext::TempoMapScope tms (*this, map);
|
||||
double width = bg->width();
|
||||
samplecnt_t samples = duration.samples();
|
||||
|
||||
samplecnt_t spp = floor (samples / width);
|
||||
reset_zoom (spp);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
MidiCueEditor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type)
|
||||
{
|
||||
@ -1761,3 +1692,98 @@ MidiCueEditor::selectable_owners()
|
||||
|
||||
return std::list<SelectableOwner*> ();
|
||||
}
|
||||
|
||||
void
|
||||
MidiCueEditor::trigger_prop_change (PBD::PropertyChange const & what_changed)
|
||||
{
|
||||
if (what_changed.contains (Properties::region)) {
|
||||
std::shared_ptr<MidiRegion> mr = std::dynamic_pointer_cast<MidiRegion> (ref.trigger()->the_region());
|
||||
if (mr) {
|
||||
set_region (mr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MidiCueEditor::set (TriggerReference & tref)
|
||||
{
|
||||
_update_connection.disconnect ();
|
||||
object_connections.drop_connections ();
|
||||
|
||||
ref = tref;
|
||||
|
||||
idle_update_queued.store (0);
|
||||
|
||||
ref.box()->Captured.connect (object_connections, invalidator (*this), std::bind (&MidiCueEditor::data_captured, this, _1), gui_context());
|
||||
/* Don't bind a shared_ptr<TriggerBox> within the lambda */
|
||||
TriggerBox* tb (ref.box().get());
|
||||
tb->RecEnableChanged.connect (object_connections, invalidator (*this), [&, tb]() { box_rec_enable_change (*tb); }, gui_context());
|
||||
|
||||
Stripable* st = dynamic_cast<Stripable*> (ref.box()->owner());
|
||||
assert (st);
|
||||
_track = std::dynamic_pointer_cast<MidiTrack> (st->shared_from_this());
|
||||
assert (_track);
|
||||
|
||||
view->set_track (_track);
|
||||
|
||||
_update_connection = Timers::rapid_connect (sigc::mem_fun (*this, &MidiCueEditor::maybe_update));
|
||||
_track->DropReferences.connect (object_connections, invalidator (*this), std::bind (&MidiCueEditor::unset, this), gui_context());
|
||||
ref.trigger()->PropertyChanged.connect (object_connections, invalidator (*this), std::bind (&MidiCueEditor::trigger_prop_change, this, _1), gui_context());
|
||||
|
||||
if (ref.trigger()->the_region()) {
|
||||
|
||||
std::shared_ptr<MidiRegion> mr = std::dynamic_pointer_cast<MidiRegion> (ref.trigger()->the_region());
|
||||
|
||||
if (mr) {
|
||||
set_region (mr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MidiCueEditor::unset ()
|
||||
{
|
||||
_update_connection.disconnect();
|
||||
object_connections.drop_connections ();
|
||||
_track.reset ();
|
||||
view->set_region (nullptr);
|
||||
ref = TriggerReference ();
|
||||
}
|
||||
|
||||
void
|
||||
MidiCueEditor::set_region (std::shared_ptr<ARDOUR::MidiRegion> r)
|
||||
{
|
||||
if (!r) {
|
||||
view->set_region (nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
view->set_region (r);
|
||||
|
||||
/* Compute zoom level to show entire source plus some margin if possible */
|
||||
|
||||
Temporal::timecnt_t duration = Temporal::timecnt_t (r->midi_source()->length().beats());
|
||||
|
||||
std::cerr << "new region: " << duration << std::endl;
|
||||
|
||||
bool provided = false;
|
||||
std::shared_ptr<Temporal::TempoMap> map;
|
||||
std::shared_ptr<SMFSource> smf (std::dynamic_pointer_cast<SMFSource> (r->midi_source()));
|
||||
|
||||
if (smf) {
|
||||
map = smf->tempo_map (provided);
|
||||
}
|
||||
|
||||
if (!provided) {
|
||||
map.reset (new Temporal::TempoMap (Temporal::Tempo (120, 4), Temporal::Meter (4, 4)));
|
||||
}
|
||||
|
||||
{
|
||||
EditingContext::TempoMapScope tms (*this, map);
|
||||
double width = bg->width();
|
||||
samplecnt_t samples = duration.samples();
|
||||
std::cerr << "new spp from " << samples << " / " << width << std::endl;
|
||||
samplecnt_t spp = floor (samples / width);
|
||||
reset_zoom (spp);
|
||||
}
|
||||
}
|
||||
|
@ -72,9 +72,8 @@ class MidiCueEditor : public CueEditor
|
||||
int32_t get_grid_beat_divisions (Editing::GridType gt) const { return 1; }
|
||||
int32_t get_grid_music_divisions (Editing::GridType gt, uint32_t event_state) const { return 1; }
|
||||
|
||||
void set (ARDOUR::TriggerReference&);
|
||||
void set_region (std::shared_ptr<ARDOUR::MidiRegion>);
|
||||
void set_box (std::shared_ptr<ARDOUR::TriggerBox>);
|
||||
void set_track (std::shared_ptr<ARDOUR::MidiTrack>);
|
||||
|
||||
ArdourCanvas::ScrollGroup* get_hscroll_group () const { return h_scroll_group; }
|
||||
ArdourCanvas::ScrollGroup* get_cursor_scroll_group () const { return cursor_scroll_group; }
|
||||
@ -140,6 +139,7 @@ class MidiCueEditor : public CueEditor
|
||||
void on_samples_per_pixel_changed ();
|
||||
|
||||
private:
|
||||
ARDOUR::TriggerReference ref;
|
||||
std::shared_ptr<ARDOUR::MidiTrack> _track;
|
||||
ArdourCanvas::GtkCanvasViewport* _canvas_viewport;
|
||||
ArdourCanvas::GtkCanvas* _canvas;
|
||||
@ -208,8 +208,11 @@ class MidiCueEditor : public CueEditor
|
||||
void stop_canvas_autoscroll ();
|
||||
|
||||
sigc::connection _update_connection;
|
||||
PBD::ScopedConnection track_connection;
|
||||
PBD::ScopedConnectionList object_connections;
|
||||
void maybe_update ();
|
||||
void trigger_prop_change (PBD::PropertyChange const &);
|
||||
|
||||
void unset ();
|
||||
|
||||
void visual_changer (const VisualChange&);
|
||||
void bindings_changed ();
|
||||
@ -217,7 +220,6 @@ class MidiCueEditor : public CueEditor
|
||||
void data_captured (Temporal::timecnt_t);
|
||||
bool idle_data_captured ();
|
||||
std::atomic<int> idle_update_queued;
|
||||
PBD::ScopedConnectionList capture_connections;
|
||||
Temporal::timecnt_t data_capture_duration;
|
||||
};
|
||||
|
||||
|
@ -95,7 +95,7 @@ MidiCueView::set_height (double h)
|
||||
double automation_height = h - note_area_height - velocity_height;
|
||||
|
||||
event_rect->set (ArdourCanvas::Rect (0.0, 0.0, ArdourCanvas::COORD_MAX, note_area_height));
|
||||
midi_context().set_size (ArdourCanvas::COORD_MAX, note_area_height);
|
||||
midi_context().set_size (midi_context().width(), note_area_height);
|
||||
|
||||
velocity_base->set_position (ArdourCanvas::Duple (0., note_area_height));
|
||||
velocity_base->set (ArdourCanvas::Rect (0., 0., ArdourCanvas::COORD_MAX, velocity_height));
|
||||
|
@ -236,8 +236,18 @@ MidiView::set_model (std::shared_ptr<MidiModel> m)
|
||||
assert (_midi_track);
|
||||
assert (_midi_region);
|
||||
|
||||
clear_events ();
|
||||
connections_requiring_model.drop_connections ();
|
||||
|
||||
_model = m;
|
||||
|
||||
if (!_model) {
|
||||
std::cerr << "no model!\n";
|
||||
return;
|
||||
}
|
||||
|
||||
std::cerr << "model set to " << _model << std::endl;
|
||||
|
||||
//set_height (trackview.current_height());
|
||||
|
||||
#warning paul pianorule needs these fixed
|
||||
@ -251,8 +261,6 @@ MidiView::set_model (std::shared_ptr<MidiModel> m)
|
||||
reset_width_dependent_items (_pixel_width);
|
||||
*/
|
||||
|
||||
connections_requiring_model.drop_connections ();
|
||||
|
||||
_model->ContentsChanged.connect (connections_requiring_model, invalidator (*this), std::bind (&MidiView::model_changed, this), gui_context());
|
||||
|
||||
_midi_track->playback_filter().ChannelModeChanged.connect (connections_requiring_model, invalidator (*this),
|
||||
@ -849,9 +857,8 @@ MidiView::clear_events ()
|
||||
{
|
||||
// clear selection without signaling or trying to change state of event objects
|
||||
_selection.clear ();
|
||||
|
||||
clear_ghost_events ();
|
||||
|
||||
/* This will delete all the NoteBase* in the _events map */
|
||||
_note_group->clear (true);
|
||||
_events.clear();
|
||||
_patch_changes.clear();
|
||||
@ -863,8 +870,6 @@ void
|
||||
MidiView::display_model (std::shared_ptr<MidiModel> model)
|
||||
{
|
||||
set_model (_model);
|
||||
/* Don't signal as nobody else needs to know until selection has been altered. */
|
||||
clear_events();
|
||||
model_changed ();
|
||||
}
|
||||
|
||||
@ -1099,14 +1104,16 @@ MidiView::model_changed()
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_model) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (_optimization_iterator = _events.begin(); _optimization_iterator != _events.end(); ++_optimization_iterator) {
|
||||
_optimization_iterator->second->invalidate ();
|
||||
}
|
||||
|
||||
/* note that _optimization_iterator now points to _events.end() */
|
||||
|
||||
if (!_model) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool empty_when_starting = _events.empty();
|
||||
_optimization_iterator = _events.begin();
|
||||
MidiModel::Notes missing_notes;
|
||||
@ -1588,6 +1595,7 @@ void
|
||||
MidiView::end_write()
|
||||
{
|
||||
if (_active_notes) {
|
||||
std::cerr << "active notes deleted in end_write\n";
|
||||
for (unsigned i = 0; i < 128; ++i) {
|
||||
delete _active_notes[i];
|
||||
}
|
||||
|
@ -419,23 +419,7 @@ TriggerPage::rec_enable_changed (Trigger const * trigger)
|
||||
_midi_trig_box.set_trigger (ref);
|
||||
_midi_trig_box.show ();
|
||||
|
||||
_midi_editor->set_box (trigger->boxptr());
|
||||
|
||||
Stripable* st = dynamic_cast<Stripable*> (box.owner());
|
||||
assert (st);
|
||||
std::shared_ptr<MidiTrack> mt = std::dynamic_pointer_cast<MidiTrack> (st->shared_from_this());
|
||||
assert (mt);
|
||||
_midi_editor->set_track (mt);
|
||||
|
||||
if (trigger->the_region()) {
|
||||
|
||||
std::shared_ptr<MidiRegion> mr = std::dynamic_pointer_cast<MidiRegion> (trigger->the_region());
|
||||
|
||||
if (mr) {
|
||||
_midi_editor->set_region (mr);
|
||||
}
|
||||
}
|
||||
|
||||
_midi_editor->set (ref);
|
||||
_midi_editor->viewport().show ();
|
||||
}
|
||||
|
||||
@ -475,19 +459,7 @@ TriggerPage::selection_changed ()
|
||||
_midi_trig_box.set_trigger (ref);
|
||||
_midi_trig_box.show ();
|
||||
|
||||
std::shared_ptr<MidiTrack> mt = std::dynamic_pointer_cast<MidiTrack> (entry->strip().stripable());
|
||||
assert (mt);
|
||||
_midi_editor->set_track (mt);
|
||||
|
||||
if (trigger->the_region()) {
|
||||
|
||||
std::shared_ptr<MidiRegion> mr = std::dynamic_pointer_cast<MidiRegion> (trigger->the_region());
|
||||
|
||||
if (mr) {
|
||||
_midi_editor->set_region (mr);
|
||||
}
|
||||
}
|
||||
|
||||
_midi_editor->set (ref);
|
||||
_midi_editor->viewport().show ();
|
||||
}
|
||||
|
||||
|
@ -41,6 +41,7 @@ class ViewBackground
|
||||
virtual ~ViewBackground ();
|
||||
|
||||
virtual double height() const { return 0.; }
|
||||
virtual double width() const { return 0.; }
|
||||
virtual double contents_height() const { return 0.; }
|
||||
|
||||
/** @return y position, or -1 if hidden */
|
||||
|
@ -127,6 +127,7 @@ TriggerBox::all_trigger_props()
|
||||
all.add(Properties::patch_change);
|
||||
all.add(Properties::channel_map);
|
||||
all.add(Properties::used_channels);
|
||||
all.add(Properties::region);
|
||||
|
||||
return all;
|
||||
}
|
||||
@ -313,7 +314,6 @@ Trigger::arm ()
|
||||
void
|
||||
Trigger::disarm ()
|
||||
{
|
||||
_box.disarm ();
|
||||
_armed = false;
|
||||
ArmChanged(); /* EMIT SIGNAL */
|
||||
TriggerArmChanged (this);
|
||||
@ -1965,10 +1965,12 @@ AudioTrigger::captured (SlotArmInfo& ai, BufferSet&)
|
||||
delete &ai; // XXX delete is not RT-safe
|
||||
|
||||
_box.queue_explict (index());
|
||||
TriggerBox::worker->request_build_source (this);
|
||||
|
||||
_armed = false;
|
||||
ArmChanged(); /* EMIT SIGNAL */
|
||||
TriggerArmChanged (this);
|
||||
|
||||
TriggerBox::worker->request_build_source (this, timecnt_t (data.length));
|
||||
}
|
||||
|
||||
int
|
||||
@ -2438,6 +2440,7 @@ void
|
||||
MIDITrigger::captured (SlotArmInfo& ai, BufferSet& bufs)
|
||||
{
|
||||
if (ai.midi_buf->size() == 0) {
|
||||
std::cerr << "nothing recorded\n";
|
||||
_armed = false;
|
||||
ArmChanged(); /* EMIT SIGNAL */
|
||||
delete &ai;
|
||||
@ -2468,10 +2471,13 @@ MIDITrigger::captured (SlotArmInfo& ai, BufferSet& bufs)
|
||||
_box.queue_explict (index());
|
||||
|
||||
/* Meanwhile, build a new source and region from the data now in rt_midibuffer */
|
||||
TriggerBox::worker->request_build_source (this);
|
||||
std::cerr << "request source ...\n";
|
||||
|
||||
_armed = false;
|
||||
ArmChanged(); /* EMIT SIGNAL */
|
||||
TriggerArmChanged (this);
|
||||
|
||||
TriggerBox::worker->request_build_source (this, timecnt_t (data_length));
|
||||
}
|
||||
|
||||
void
|
||||
@ -2946,6 +2952,8 @@ MIDITrigger::set_region_in_worker_thread_from_capture (std::shared_ptr<Region> r
|
||||
{
|
||||
assert (r);
|
||||
|
||||
std::cerr << "SRIWTFC " << r->name() << std::endl;
|
||||
|
||||
std::shared_ptr<MidiRegion> mr = std::dynamic_pointer_cast<MidiRegion> (r);
|
||||
|
||||
if (!mr) {
|
||||
@ -2966,7 +2974,8 @@ MIDITrigger::set_region_in_worker_thread_from_capture (std::shared_ptr<Region> r
|
||||
/* This is being used as a kind of shorthand for "everything" which is
|
||||
pretty stupid
|
||||
*/
|
||||
send_property_change (ARDOUR::Properties::name);
|
||||
std::cerr << "send region change\n";
|
||||
send_property_change (ARDOUR::Properties::region);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -3597,10 +3606,16 @@ TriggerBox::disarm_all ()
|
||||
void
|
||||
TriggerBox::finish_recording (BufferSet& bufs)
|
||||
{
|
||||
std::cerr << "FR!\n";
|
||||
SlotArmInfo* ai = _arm_info.load();
|
||||
assert (ai);
|
||||
|
||||
/* This transfers responsibility for the SlotArmInfo object to the
|
||||
trigger
|
||||
*/
|
||||
ai->slot.captured (*ai, bufs);
|
||||
_arm_info = nullptr;
|
||||
_record_state = Disabled;
|
||||
}
|
||||
|
||||
void
|
||||
|
Loading…
Reference in New Issue
Block a user