Adding sends/port inserts to MIDI tracks (not actually working yet though)
[ardour.git] / libs / ardour / midi_track.cc
index 470759f3ac3c987d11cbb6c1465e31ba7a46ace5..2336baac75965f7443287adef6fd0a7271084f72 100644 (file)
@@ -32,6 +32,7 @@
 #include <ardour/midi_playlist.h>
 #include <ardour/panner.h>
 #include <ardour/utils.h>
+#include <ardour/buffer_set.h>
 
 #include "i18n.h"
 
@@ -50,18 +51,22 @@ MidiTrack::MidiTrack (Session& sess, string name, Route::Flag flag, TrackMode mo
                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)
@@ -71,24 +76,22 @@ 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);
 
@@ -106,33 +109,33 @@ MidiTrack::set_diskstream (MidiDiskstream& ds)
 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);
+       return set_diskstream (dstream);
 }
 
-MidiDiskstream&
+boost::shared_ptr<MidiDiskstream>
 MidiTrack::midi_diskstream() const
 {
-       return *dynamic_cast<MidiDiskstream*>(_diskstream);
+       return boost::dynamic_pointer_cast<MidiDiskstream>(_diskstream);
 }
 
 int
@@ -348,29 +351,18 @@ MidiTrack::set_state_part_two ()
        return;
 }      
 
-ChanCount
-MidiTrack::n_process_buffers ()
-{
-       return max (_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)
-{
-       process_output_buffers (_session.get_silent_buffers (n_process_buffers()), 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().get(DataType::MIDI) == 0) {
-               return 0;
+               //return 0;
+               throw; // FIXME
        }
 
        if (!_active) {
                silence (nframes, offset);
-               return 0;
+               //return 0; // FIXME
        }
 
        if (session_state_changing) {
@@ -381,7 +373,7 @@ MidiTrack::no_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nfr
                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;
        
@@ -444,13 +436,9 @@ int
 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)
 {
-       //passthru (start_frame, end_frame, nframes, offset, declick, false);
        int dret;
-       RawMidi* b; // FIXME: this won't work, duh
-       //Sample* tmpb;
-       jack_nframes_t transport_frame;
-       MidiDiskstream& diskstream = midi_diskstream();
-       
+       boost::shared_ptr<MidiDiskstream> diskstream = midi_diskstream();
+
        {
                Glib::RWLock::ReaderLock lm (redirect_lock, Glib::TRY_LOCK);
                if (lm.locked()) {
@@ -459,7 +447,7 @@ MidiTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframe
                        automation_snapshot (start_frame);
                }
        }
-       
+
        if (n_outputs().get_total() == 0 && _redirects.empty()) {
                return 0;
        }
@@ -469,83 +457,59 @@ MidiTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframe
                return 0;
        }
 
-       transport_frame = _session.transport_frame();
+       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);
+                  */
+               return diskstream->process (transport_frame, 0, 0, can_record, rec_monitors_input);
        } 
 
        _silent = false;
-       //apply_gain_automation = false;
 
-       if ((dret = diskstream.process (transport_frame, nframes, offset, can_record, rec_monitors_input)) != 0) {
-               
+       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()) {
+       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 if ((b = diskstream.playback_buffer()) != 0) {
+       } 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.
-               */
+                  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());
-               
-               //uint32_t n;
-               //uint32_t i;
-#if 0
-               for (i = 0, n = 1; i < limit; ++i, ++n) {
-                       memcpy (bufs.get_audio(i).data(nframes), b, sizeof (Sample) * nframes); 
-                       if (n < diskstream.n_channels().get(DataType::AUDIO)) {
-                               tmpb = diskstream.playback_buffer(n);
-                               if (tmpb!=0) {
-                                       b = tmpb;
-                               }
-                       }
-               }
 
-               /* don't waste time with automation if we're recording or we've just stopped (yes it can happen) */
+               diskstream->get_playback(bufs.get_midi(0), start_frame, end_frame);
 
-               if (!diskstream.record_enabled() && _session.transport_rolling()) {
-                       Glib::Mutex::Lock am (automation_lock, Glib::TRY_LOCK);
-                       
-                       if (am.locked() && gain_automation_playback()) {
-                               apply_gain_automation = _gain_automation_curve.rt_safe_get_vector (start_frame, end_frame, _session.gain_automation_buffer(), nframes);
-                       }
-               }
-#endif
-               process_output_buffers (bufs, start_frame, end_frame, nframes, offset, (!_session.get_record_enabled() || !_session.get_do_not_record_plugins()), declick, (_meter_point != MeterInput));
-               
-       } else {
-               /* problem with the diskstream; just be quiet for a bit */
-               silence (nframes, offset);
+               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;
@@ -569,7 +533,7 @@ MidiTrack::silent_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack
 
        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
@@ -584,7 +548,6 @@ MidiTrack::process_output_buffers (BufferSet& bufs,
        // 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);