#include <ardour/midi_playlist.h>
#include <ardour/panner.h>
#include <ardour/utils.h>
+#include <ardour/buffer_set.h>
#include "i18n.h"
dflags = MidiDiskstream::Flag (dflags | MidiDiskstream::Recordable);
}
- if (mode == Destructive) {
- dflags = MidiDiskstream::Flag (dflags | MidiDiskstream::Destructive);
- }
+ assert(mode != Destructive);
+
+ boost::shared_ptr<MidiDiskstream> ds (new MidiDiskstream (_session, name, dflags));
+ _session.add_diskstream (ds);
- MidiDiskstream* ds = new MidiDiskstream (_session, name, dflags);
+ set_diskstream (boost::dynamic_pointer_cast<MidiDiskstream> (ds));
_declickable = true;
_freeze_record.state = NoFreeze;
_saved_meter_point = _meter_point;
_mode = mode;
- set_diskstream (*ds);
+ set_input_minimum(ChanCount(DataType::MIDI, 1));
+ set_input_maximum(ChanCount(DataType::MIDI, 1));
+ set_output_minimum(ChanCount(DataType::MIDI, 1));
+ set_output_maximum(ChanCount(DataType::MIDI, 1));
}
MidiTrack::MidiTrack (Session& sess, const XMLNode& node)
set_state (node);
_declickable = true;
_saved_meter_point = _meter_point;
+
+ set_input_minimum(ChanCount(DataType::MIDI, 1));
+ set_input_maximum(ChanCount(DataType::MIDI, 1));
+ set_output_minimum(ChanCount(DataType::MIDI, 1));
+ set_output_maximum(ChanCount(DataType::MIDI, 1));
}
MidiTrack::~MidiTrack ()
{
- if (_diskstream) {
- _diskstream->unref();
- }
}
int
-MidiTrack::set_diskstream (MidiDiskstream& ds)
+MidiTrack::set_diskstream (boost::shared_ptr<MidiDiskstream> ds)
{
- if (_diskstream) {
- _diskstream->unref();
- }
-
- _diskstream = &ds.ref();
+ _diskstream = ds;
_diskstream->set_io (*this);
_diskstream->set_destructive (_mode == Destructive);
int
MidiTrack::use_diskstream (string name)
{
- MidiDiskstream *dstream;
+ boost::shared_ptr<MidiDiskstream> dstream;
- if ((dstream = dynamic_cast<MidiDiskstream*>(_session.diskstream_by_name (name))) == 0) {
- error << string_compose(_("MidiTrack: midi diskstream \"%1\" not known by session"), name) << endmsg;
+ if ((dstream = boost::dynamic_pointer_cast<MidiDiskstream>(_session.diskstream_by_name (name))) == 0) {
+ error << string_compose(_("MidiTrack: midi diskstream \"%1\" not known by session"), name) << endmsg;
return -1;
}
- return set_diskstream (*dstream);
+ return set_diskstream (dstream);
}
int
MidiTrack::use_diskstream (const PBD::ID& id)
{
- MidiDiskstream *dstream;
+ boost::shared_ptr<MidiDiskstream> dstream;
- if ((dstream = dynamic_cast<MidiDiskstream*>(_session.diskstream_by_id (id))) == 0) {
+ if ((dstream = boost::dynamic_pointer_cast<MidiDiskstream> (_session.diskstream_by_id (id))) == 0) {
error << string_compose(_("MidiTrack: midi diskstream \"%1\" not known by session"), id) << endmsg;
return -1;
}
- return set_diskstream (*dstream);
-}
-
-bool
-MidiTrack::record_enabled () const
-{
- return _diskstream->record_enabled ();
+ return set_diskstream (dstream);
}
-void
-MidiTrack::set_record_enable (bool yn, void *src)
-{
- if (_freeze_record.state == Frozen) {
- return;
- }
-#if 0
- if (_mix_group && src != _mix_group && _mix_group->is_active()) {
- _mix_group->apply (&MidiTrack::set_record_enable, yn, _mix_group);
- return;
- }
-
- /* keep track of the meter point as it was before we rec-enabled */
-
- if (!diskstream->record_enabled()) {
- _saved_meter_point = _meter_point;
- }
-
- diskstream->set_record_enabled (yn, src);
-
- if (diskstream->record_enabled()) {
- set_meter_point (MeterInput, this);
- } else {
- set_meter_point (_saved_meter_point, this);
- }
-
- if (_session.get_midi_feedback()) {
- _midi_rec_enable_control.send_feedback (record_enabled());
- }
-#endif
-}
-
-MidiDiskstream&
+boost::shared_ptr<MidiDiskstream>
MidiTrack::midi_diskstream() const
{
- return *dynamic_cast<MidiDiskstream*>(_diskstream);
+ return boost::dynamic_pointer_cast<MidiDiskstream>(_diskstream);
}
int
return;
}
-uint32_t
-MidiTrack::n_process_buffers ()
-{
- return max ((uint32_t) _diskstream->n_channels(), redirect_max_outs);
-}
-
-void
-MidiTrack::passthru_silence (jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t nframes, jack_nframes_t offset, int declick, bool meter)
-{
- uint32_t nbufs = n_process_buffers ();
- process_output_buffers (_session.get_silent_buffers (nbufs), nbufs, start_frame, end_frame, nframes, offset, true, declick, meter);
-}
-
int
MidiTrack::no_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t offset,
bool session_state_changing, bool can_record, bool rec_monitors_input)
{
- if (n_outputs() == 0) {
- return 0;
+ if (n_outputs().get(DataType::MIDI) == 0) {
+ //return 0;
+ throw; // FIXME
}
if (!_active) {
silence (nframes, offset);
- return 0;
+ //return 0; // FIXME
}
if (session_state_changing) {
return 0;
}
- midi_diskstream().check_record_status (start_frame, nframes, can_record);
+ midi_diskstream()->check_record_status (start_frame, nframes, can_record);
bool send_silence;
MidiTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t offset, int declick,
bool can_record, bool rec_monitors_input)
{
+ int dret;
+ boost::shared_ptr<MidiDiskstream> diskstream = midi_diskstream();
+
+ {
+ Glib::RWLock::ReaderLock lm (redirect_lock, Glib::TRY_LOCK);
+ if (lm.locked()) {
+ // automation snapshot can also be called from the non-rt context
+ // and it uses the redirect list, so we take the lock out here
+ automation_snapshot (start_frame);
+ }
+ }
+
+ if (n_outputs().get_total() == 0 && _redirects.empty()) {
+ return 0;
+ }
+
+ if (!_active) {
+ silence (nframes, offset);
+ return 0;
+ }
+
+ jack_nframes_t transport_frame = _session.transport_frame();
+
+ if ((nframes = check_initial_delay (nframes, offset, transport_frame)) == 0) {
+ /* need to do this so that the diskstream sets its
+ playback distance to zero, thus causing diskstream::commit
+ to do nothing.
+ */
+ return diskstream->process (transport_frame, 0, 0, can_record, rec_monitors_input);
+ }
+
+ _silent = false;
+
+ if ((dret = diskstream->process (transport_frame, nframes, offset, can_record, rec_monitors_input)) != 0) {
+
+ silence (nframes, offset);
+
+ return dret;
+ }
+
+ /* special condition applies */
+
+ if (_meter_point == MeterInput) {
+ just_meter_input (start_frame, end_frame, nframes, offset);
+ }
+
+ if (diskstream->record_enabled() && !can_record && !_session.get_auto_input()) {
+
+ /* not actually recording, but we want to hear the input material anyway,
+ at least potentially (depending on monitoring options)
+ */
+
+ passthru (start_frame, end_frame, nframes, offset, 0, true);
+
+ } else {
+ /*
+ XXX is it true that the earlier test on n_outputs()
+ means that we can avoid checking it again here? i think
+ so, because changing the i/o configuration of an IO
+ requires holding the AudioEngine lock, which we hold
+ while in the process() tree.
+ */
+
+
+ /* copy the diskstream data to all output buffers */
+
+ //const size_t limit = n_process_buffers().get(DataType::AUDIO);
+ BufferSet& bufs = _session.get_scratch_buffers (n_process_buffers());
+
+ diskstream->get_playback(bufs.get_midi(0), start_frame, end_frame);
+
+ process_output_buffers (bufs, start_frame, end_frame, nframes, offset,
+ (!_session.get_record_enabled() || !_session.get_do_not_record_plugins()), declick, (_meter_point != MeterInput));
+
+ }
+
return 0;
}
MidiTrack::silent_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t offset,
bool can_record, bool rec_monitors_input)
{
- if (n_outputs() == 0 && _redirects.empty()) {
+ if (n_outputs().get(DataType::MIDI) == 0 && _redirects.empty()) {
return 0;
}
silence (nframes, offset);
- return midi_diskstream().process (_session.transport_frame() + offset, nframes, offset, can_record, rec_monitors_input);
+ return midi_diskstream()->process (_session.transport_frame() + offset, nframes, offset, can_record, rec_monitors_input);
+}
+
+void
+MidiTrack::process_output_buffers (BufferSet& bufs,
+ jack_nframes_t start_frame, jack_nframes_t end_frame,
+ jack_nframes_t nframes, jack_nframes_t offset, bool with_redirects, int declick,
+ bool meter)
+{
+ // There's no such thing as a MIDI bus for the time being, to avoid diverging from trunk
+ // too much until the SoC settles down. We'll do all the MIDI route work here for now
+
+ // Main output stage is the only stage we've got.
+ // I think it's a pretty good stage though, wouldn't you say?
+
+ if (muted()) {
+
+ IO::silence(nframes, offset);
+
+ } else {
+
+ deliver_output(bufs, start_frame, end_frame, nframes, offset);
+
+ }
+
}
int
}
int
-MidiTrack::export_stuff (vector<unsigned char*>& buffers, char * workbuf, uint32_t nbufs, jack_nframes_t start, jack_nframes_t nframes)
+MidiTrack::export_stuff (BufferSet& bufs, jack_nframes_t nframes, jack_nframes_t end_frame)
{
- return 0;
+ return -1;
}
void
void
MidiTrack::bounce (InterThreadInfo& itt)
{
+ throw;
//vector<MidiSource*> srcs;
//_session.write_one_midi_track (*this, 0, _session.current_end_frame(), false, srcs, itt);
}
void
MidiTrack::bounce_range (jack_nframes_t start, jack_nframes_t end, InterThreadInfo& itt)
{
+ throw;
//vector<MidiSource*> srcs;
//_session.write_one_midi_track (*this, start, end, false, srcs, itt);
}