Fix a few framecnt / framepos type confusions.
[ardour.git] / libs / ardour / midi_track.cc
index dcea38521bb3ec34104443831a51b38755526b17..e99df0ffb952417ceb8e3b4ab9dba6ae11b49de1 100644 (file)
@@ -77,8 +77,8 @@ MidiTrack::init ()
        return 0;
 }
 
-void
-MidiTrack::use_new_diskstream ()
+boost::shared_ptr<Diskstream>
+MidiTrack::create_diskstream ()
 {
        MidiDiskstream::Flag dflags = MidiDiskstream::Flag (0);
 
@@ -90,13 +90,10 @@ MidiTrack::use_new_diskstream ()
 
        assert(_mode != Destructive);
 
-       boost::shared_ptr<MidiDiskstream> ds (new MidiDiskstream (_session, name(), dflags));
-       ds->do_refill_with_alloc ();
-       ds->set_block_size (_session.get_block_size ());
-
-       set_diskstream (ds);
+       return boost::shared_ptr<Diskstream> (new MidiDiskstream (_session, name(), dflags));
 }
 
+
 void
 MidiTrack::set_record_enabled (bool yn, void *src)
 {
@@ -112,17 +109,17 @@ MidiTrack::set_diskstream (boost::shared_ptr<Diskstream> ds)
 {
        Track::set_diskstream (ds);
 
+       midi_diskstream()->reset_tracker ();    
+
        _diskstream->set_track (this);
        _diskstream->set_destructive (_mode == Destructive);
-
        _diskstream->set_record_enabled (false);
-       //_diskstream->monitor_input (false);
 
        _diskstream_data_recorded_connection.disconnect ();
        boost::shared_ptr<MidiDiskstream> mds = boost::dynamic_pointer_cast<MidiDiskstream> (ds);
        mds->DataRecorded.connect_same_thread (
                _diskstream_data_recorded_connection,
-               boost::bind (&MidiTrack::diskstream_data_recorded, this, _1, _2));
+               boost::bind (&MidiTrack::diskstream_data_recorded, this, _1));
 
        DiskstreamChanged (); /* EMIT SIGNAL */
 }
@@ -135,16 +132,10 @@ MidiTrack::midi_diskstream() const
 
 int
 MidiTrack::set_state (const XMLNode& node, int version)
-{
-       return _set_state (node, version);
-}
-
-int
-MidiTrack::_set_state (const XMLNode& node, int version)
 {
        const XMLProperty *prop;
 
-       if (Track::_set_state (node, version)) {
+       if (Track::set_state (node, version)) {
                return -1;
        }
 
@@ -278,15 +269,17 @@ MidiTrack::set_state_part_two ()
        return;
 }
 
+/** @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, framepos_t start_frame, framepos_t end_frame, int declick, bool& needs_butler)
+MidiTrack::roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, int declick, bool& need_butler)
 {
        Glib::RWLock::ReaderLock lm (_processor_lock, Glib::TRY_LOCK);
        if (!lm.locked()) {
                return 0;
        }
 
-       int dret;
        boost::shared_ptr<MidiDiskstream> diskstream = midi_diskstream();
 
        automation_snapshot (start_frame);
@@ -302,17 +295,23 @@ MidiTrack::roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame
 
        framepos_t transport_frame = _session.transport_frame();
 
+       int dret;
+       framecnt_t playback_distance;
+
        if ((nframes = check_initial_delay (nframes, 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, needs_butler);
+               dret = diskstream->process (transport_frame, 0, playback_distance);
+               need_butler = diskstream->commit (playback_distance);
+               return dret;
        }
 
        _silent = false;
 
-       if ((dret = diskstream->process (transport_frame, nframes, needs_butler)) != 0) {
+       if ((dret = diskstream->process (transport_frame, nframes, playback_distance)) != 0) {
+               need_butler = diskstream->commit (playback_distance);
                silence (nframes);
                return dret;
        }
@@ -353,7 +352,7 @@ MidiTrack::roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame
                c.set_midi (1);
                bufs.set_count (c);
 
-               diskstream->get_playback (mbuf, start_frame, end_frame);
+               diskstream->get_playback (mbuf, nframes);
 
                /* append immediate messages to the first MIDI buffer (thus sending it to the first output port) */
 
@@ -361,18 +360,21 @@ MidiTrack::roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame
 
                /* final argument: don't waste time with automation if we're recording or we've just stopped (yes it can happen) */
 
-               process_output_buffers (bufs, start_frame, end_frame, nframes,
-                                       (!_session.get_record_enabled() || !Config->get_do_not_record_plugins()), declick,
-                                       (!diskstream->record_enabled() && !_session.transport_stopped()));
+               process_output_buffers (
+                       bufs, start_frame, end_frame, nframes,
+                       declick, (!diskstream->record_enabled() && !_session.transport_stopped())
+                       );
        }
 
        for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
                boost::shared_ptr<Delivery> d = boost::dynamic_pointer_cast<Delivery> (*i);
                if (d) {
-                       d->flush_buffers (nframes, end_frame - start_frame - 1);
+                       d->flush_buffers (nframes);
                }
        }
 
+       need_butler = diskstream->commit (playback_distance);
+       
        return 0;
 }
 
@@ -392,6 +394,7 @@ void
 MidiTrack::realtime_locate ()
 {
        Glib::RWLock::ReaderLock lm (_processor_lock, Glib::TRY_LOCK);
+
        if (!lm.locked ()) {
                return;
        }
@@ -399,12 +402,15 @@ MidiTrack::realtime_locate ()
        for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
                (*i)->realtime_locate ();
        }
+
+       midi_diskstream()->reset_tracker ();
 }
 
 void
 MidiTrack::realtime_handle_transport_stopped ()
 {
        Glib::RWLock::ReaderLock lm (_processor_lock, Glib::TRY_LOCK);
+
        if (!lm.locked ()) {
                return;
        }
@@ -472,7 +478,8 @@ MidiTrack::write_out_of_band_data (BufferSet& bufs, framepos_t /*start*/, framep
 }
 
 int
-MidiTrack::export_stuff (BufferSet& /*bufs*/, framecnt_t /*nframes*/, framepos_t /*end_frame*/)
+MidiTrack::export_stuff (BufferSet& /*bufs*/, framepos_t /*start_frame*/, framecnt_t /*nframes*/, 
+                        boost::shared_ptr<Processor> /*endpoint*/, bool /*include_endpoint*/, bool /*forexport*/)
 {
        return -1;
 }
@@ -486,7 +493,8 @@ MidiTrack::bounce (InterThreadInfo& /*itt*/)
 
 
 boost::shared_ptr<Region>
-MidiTrack::bounce_range (framepos_t /*start*/, framepos_t /*end*/, InterThreadInfo& /*itt*/, bool /*enable_processing*/)
+MidiTrack::bounce_range (framepos_t /*start*/, framepos_t /*end*/, InterThreadInfo& /*itt*/,
+                        boost::shared_ptr<Processor> /*endpoint*/, bool /*include_endpoint*/)
 {
        std::cerr << "MIDI bounce range currently unsupported" << std::endl;
        return boost::shared_ptr<Region> ();
@@ -647,21 +655,9 @@ MidiTrack::midi_playlist ()
 }
 
 void
-MidiTrack::diskstream_data_recorded (boost::shared_ptr<MidiBuffer> buf, boost::weak_ptr<MidiSource> src)
-{
-       DataRecorded (buf, src); /* EMIT SIGNAL */
-}
-
-bool
-MidiTrack::should_monitor () const
+MidiTrack::diskstream_data_recorded (boost::weak_ptr<MidiSource> src)
 {
-       return true;
-}
-
-bool
-MidiTrack::send_silence () const
-{
-       return false;
+       DataRecorded (src); /* EMIT SIGNAL */
 }
 
 bool
@@ -710,3 +706,76 @@ MidiTrack::diskstream_factory (XMLNode const & node)
 {
        return boost::shared_ptr<Diskstream> (new MidiDiskstream (_session, node));
 }
+
+boost::shared_ptr<MidiBuffer>
+MidiTrack::get_gui_feed_buffer () const
+{
+       return midi_diskstream()->get_gui_feed_buffer ();
+}
+
+void
+MidiTrack::act_on_mute ()
+{
+       /* this is called right after our mute status has changed.
+          if we are now muted, send suitable output to shutdown
+          all our notes.
+
+          XXX we should should also stop all relevant note trackers.
+       */
+
+       if (muted()) {
+               /* only send messages for channels we are using */
+
+               uint16_t mask = get_channel_mask();
+
+               for (uint8_t channel = 0; channel <= 0xF; channel++) {
+
+                       if ((1<<channel) & mask) {
+
+                               DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 delivers mute message to channel %2\n", name(), channel+1));
+                               uint8_t ev[3] = { MIDI_CMD_CONTROL | channel, MIDI_CTL_SUSTAIN, 0 };
+                               write_immediate_event (3, ev);
+                               ev[1] = MIDI_CTL_ALL_NOTES_OFF;
+                               write_immediate_event (3, ev);
+                       }
+               }
+       }
+}
+       
+void
+MidiTrack::set_monitoring (MonitorChoice mc)
+{
+       Track::set_monitoring (mc);
+
+       boost::shared_ptr<MidiDiskstream> md (midi_diskstream());
+
+       if (md) {
+               md->reset_tracker ();
+       }
+}
+
+MonitorState
+MidiTrack::monitoring_state () const
+{
+       /* Explicit requests */
+       
+       if (_monitoring & MonitorInput) {
+               return MonitoringInput;
+       }
+               
+       if (_monitoring & MonitorDisk) {
+               return MonitoringDisk;
+       }
+
+       if (_session.transport_rolling()) {
+               return MonitoringDisk;
+       } 
+
+       /* the return value here doesn't mean that we're actually monitoring
+        * input, let alone input *audio*. but it means that we are NOT 
+        * monitoring silence. this allows us to still hear any audio generated
+        * by using internal generation techniques
+        */
+
+       return MonitoringInput;
+}