X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fmidi_track.cc;h=a6a3b9f6f8b69268a99c80f3e77e463185a2afcd;hb=8cf323c15df3af076a7e69a4b24c5cb6329477c6;hp=91916bd914f93f24ed271e32318ca8f72ec7ab4c;hpb=30b087ab3d28f1585987fa3f6ae006562ae192e3;p=ardour.git diff --git a/libs/ardour/midi_track.cc b/libs/ardour/midi_track.cc index 91916bd914..a6a3b9f6f8 100644 --- a/libs/ardour/midi_track.cc +++ b/libs/ardour/midi_track.cc @@ -73,6 +73,7 @@ using namespace PBD; MidiTrack::MidiTrack (Session& sess, string name, TrackMode mode) : Track (sess, name, PresentationInfo::MidiTrack, mode, DataType::MIDI) , _immediate_events(6096) // FIXME: size? + , _immediate_event_buffer(6096) , _step_edit_ring_buffer(64) // FIXME: size? , _note_mode (Sustained) , _step_editing (false) @@ -97,9 +98,17 @@ MidiTrack::init () _disk_writer->set_note_mode (_note_mode); _disk_reader->reset_tracker (); + _disk_writer->DataRecorded.connect_same_thread (*this, boost::bind (&MidiTrack::data_recorded, this, _1)); + return 0; } +void +MidiTrack::data_recorded (boost::weak_ptr src) +{ + DataRecorded (src); /* EMIT SIGNAL */ +} + bool MidiTrack::can_be_record_safe () { @@ -186,9 +195,9 @@ MidiTrack::set_state (const XMLNode& node, int version) } XMLNode& -MidiTrack::state(bool full_state) +MidiTrack::state(bool save_template) { - XMLNode& root (Track::state(full_state)); + XMLNode& root (Track::state (save_template)); XMLNode* freeze_node; char buf[64]; @@ -303,79 +312,27 @@ MidiTrack::restore_controls () } void -MidiTrack::update_controls(const BufferSet& bufs) +MidiTrack::update_controls (BufferSet const& bufs) { const MidiBuffer& buf = bufs.get_midi(0); for (MidiBuffer::const_iterator e = buf.begin(); e != buf.end(); ++e) { - const Evoral::Event& ev = *e; + const Evoral::Event& ev = *e; const Evoral::Parameter param = midi_parameter(ev.buffer(), ev.size()); const boost::shared_ptr control = automation_control (param); if (control) { - control->set_double(ev.value(), _session.transport_sample(), false); - control->Changed (false, Controllable::NoGroup); + double old = control->get_double (false, 0); + control->set_double (ev.value(), 0, false); + if (old != ev.value()) { + control->Changed (false, Controllable::NoGroup); + } } } } -/** @param need_butler to be set to true if this track now needs the butler, otherwise it can be left alone - * or set to false. - */ int -MidiTrack::roll (pframes_t nframes, samplepos_t start_sample, samplepos_t end_sample, int declick, bool& need_butler) +MidiTrack::no_roll_unlocked (pframes_t nframes, samplepos_t start_sample, samplepos_t end_sample, bool state_changing) { - Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK); - - if (!lm.locked()) { - return 0; - } - - if (n_outputs().n_total() == 0 && _processors.empty()) { - return 0; - } - - if (!_active) { - silence (nframes); - if (_meter_point == MeterInput && ((_monitoring_control->monitoring_choice() & MonitorInput) || _disk_writer->record_enabled())) { - _meter->reset(); - } - return 0; - } - - _silent = false; - _amp->apply_gain_automation (false); - - BufferSet& bufs = _session.get_route_buffers (n_process_buffers()); - - fill_buffers_with_input (bufs, _input, nframes); - - /* filter captured data before meter sees it */ - _capture_filter.filter (bufs); - - if (_meter_point == MeterInput && ((_monitoring_control->monitoring_choice() & MonitorInput) || _disk_writer->record_enabled())) { - _meter->run (bufs, start_sample, end_sample, 1.0 /*speed()*/, nframes, true); - } - - /* append immediate messages to the first MIDI buffer (thus sending it to the first output port) */ - - write_out_of_band_data (bufs, start_sample, end_sample, nframes); - - /* final argument: don't waste time with automation if we're not recording or rolling */ - - process_output_buffers (bufs, start_sample, end_sample, nframes, declick, (!_disk_writer->record_enabled() && !_session.transport_stopped())); - - if (_disk_reader->need_butler() || _disk_writer->need_butler()) { - need_butler = true; - } - - flush_processor_buffers_locked (nframes); - - return 0; -} - -int -MidiTrack::no_roll (pframes_t nframes, samplepos_t start_sample, samplepos_t end_sample, bool state_changing) -{ - int ret = Track::no_roll (nframes, start_sample, end_sample, state_changing); + int ret = Track::no_roll_unlocked (nframes, start_sample, end_sample, state_changing); if (ret == 0 && _step_editing) { push_midi_input_to_step_edit_ringbuffer (nframes); @@ -435,7 +392,7 @@ MidiTrack::non_realtime_locate (samplepos_t pos) boost::shared_ptr rcontrol; if ((tcontrol = boost::dynamic_pointer_cast(c->second)) && (rcontrol = region->control(tcontrol->parameter()))) { - const Evoral::Beats pos_beats = bfc.from(pos - origin); + const Temporal::Beats pos_beats = bfc.from(pos - origin); if (rcontrol->list()->size() > 0) { tcontrol->set_value(rcontrol->list()->eval(pos_beats.to_double()), Controllable::NoGroup); } @@ -471,30 +428,35 @@ MidiTrack::push_midi_input_to_step_edit_ringbuffer (samplecnt_t nframes) } void -MidiTrack::write_out_of_band_data (BufferSet& bufs, samplepos_t /*start*/, samplepos_t /*end*/, samplecnt_t nframes) +MidiTrack::snapshot_out_of_band_data (samplecnt_t nframes) { - MidiBuffer& buf (bufs.get_midi (0)); - - update_controls (bufs); + _immediate_event_buffer.clear (); + if (0 == _immediate_events.read_space()) { + return; + } - // Append immediate events + assert (nframes > 0); - if (_immediate_events.read_space()) { + DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 has %2 of immediate events to deliver\n", + name(), _immediate_events.read_space())); - DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 has %2 of immediate events to deliver\n", - name(), _immediate_events.read_space())); + /* write as many of the immediate events as we can, but give "true" as + * the last argument ("stop on overflow in destination") so that we'll + * ship the rest out next time. + * + * the Port::port_offset() + (nframes-1) argument puts all these events at the last + * possible position of the output buffer, so that we do not + * violate monotonicity when writing. Port::port_offset() will + * be non-zero if we're in a split process cycle. + */ + _immediate_events.read (_immediate_event_buffer, 0, 1, Port::port_offset() + nframes - 1, true); +} - /* write as many of the immediate events as we can, but give "true" as - * the last argument ("stop on overflow in destination") so that we'll - * ship the rest out next time. - * - * the Port::port_offset() + (nframes-1) argument puts all these events at the last - * possible position of the output buffer, so that we do not - * violate monotonicity when writing. Port::port_offset() will - * be non-zero if we're in a split process cycle. - */ - _immediate_events.read (buf, 0, 1, Port::port_offset() + nframes - 1, true); - } +void +MidiTrack::write_out_of_band_data (BufferSet& bufs, samplecnt_t nframes) const +{ + MidiBuffer& buf (bufs.get_midi (0)); + buf.merge_from (_immediate_event_buffer, nframes); } int @@ -790,7 +752,7 @@ MidiTrack::track_input_active (IOChange change, void* /* src */) boost::shared_ptr MidiTrack::get_gui_feed_buffer () const { - return _disk_reader->get_gui_feed_buffer (); + return _disk_writer->get_gui_feed_buffer (); } void @@ -863,3 +825,9 @@ MidiTrack::monitoring_state () const } return ms; } + +void +MidiTrack::filter_input (BufferSet& bufs) +{ + _capture_filter.filter (bufs); +}