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)
_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<MidiSource> src)
+{
+ DataRecorded (src); /* EMIT SIGNAL */
+}
+
bool
MidiTrack::can_be_record_safe ()
{
}
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];
}
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<samplepos_t>& ev = *e;
+ const Evoral::Event<samplepos_t>& ev = *e;
const Evoral::Parameter param = midi_parameter(ev.buffer(), ev.size());
const boost::shared_ptr<AutomationControl> 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);
boost::shared_ptr<Evoral::Control> rcontrol;
if ((tcontrol = boost::dynamic_pointer_cast<MidiTrack::MidiControl>(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);
}
}
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
boost::shared_ptr<MidiBuffer>
MidiTrack::get_gui_feed_buffer () const
{
- return _disk_reader->get_gui_feed_buffer ();
+ return _disk_writer->get_gui_feed_buffer ();
}
void
}
return ms;
}
+
+void
+MidiTrack::filter_input (BufferSet& bufs)
+{
+ _capture_filter.filter (bufs);
+}