Fix displaying of notes in auto-created MIDI region when it's the first region in...
[ardour.git] / libs / ardour / midi_diskstream.cc
index 0626f6d423cf0cb68295572e906b7b754b969789..3a2842be7a91fcbd23be6381667dce46d389c2e8 100644 (file)
@@ -68,6 +68,7 @@ MidiDiskstream::MidiDiskstream (Session &sess, const string &name, Diskstream::F
        , _source_port(0)
        , _capture_transition_buf(0)
        , _last_flush_frame(0)
+       , _note_mode(Sustained)
 {
        /* prevent any write sources from being created */
 
@@ -92,6 +93,7 @@ MidiDiskstream::MidiDiskstream (Session& sess, const XMLNode& node)
        , _source_port(0)
        , _capture_transition_buf(0)
        , _last_flush_frame(0)
+       , _note_mode(Sustained)
 {
        in_set_state = true;
        init (Recordable);
@@ -135,6 +137,17 @@ MidiDiskstream::~MidiDiskstream ()
        Glib::Mutex::Lock lm (state_lock);
 }
 
+       
+void
+MidiDiskstream::non_realtime_locate (nframes_t position)
+{
+       //cerr << "MDS: non_realtime_locate: " << position << endl;
+       assert(_write_source);
+       _write_source->set_timeline_position (position);
+       seek(position, true); // correct?
+}
+
+
 void
 MidiDiskstream::non_realtime_input_change ()
 {
@@ -194,25 +207,7 @@ MidiDiskstream::get_input_sources ()
 
        _source_port = _io->midi_input(0);
 
-       /* I don't get it....
-       const char **connections = _io->input(0)->get_connections ();
-
-       if (connections == 0 || connections[0] == 0) {
-
-               if (_source_port) {
-                       // _source_port->disable_metering ();
-               }
-
-               _source_port = 0;
-
-       } else {
-               _source_port = dynamic_cast<MidiPort*>(
-                       _session.engine().get_port_by_name (connections[0]) );
-       }
-
-       if (connections) {
-               free (connections);
-       }*/
+       // do... stuff?
 }              
 
 int
@@ -305,6 +300,15 @@ MidiDiskstream::set_destructive (bool yn)
        assert( ! yn);
        return -1;
 }
+       
+void
+MidiDiskstream::set_note_mode (NoteMode m)
+{
+       _note_mode = m;
+       midi_playlist()->set_note_mode(m);
+       if (_write_source && _write_source->model())
+               _write_source->model()->set_note_mode(m);
+}
 
 void
 MidiDiskstream::check_record_status (nframes_t transport_frame, nframes_t nframes, bool can_record)
@@ -540,9 +544,12 @@ MidiDiskstream::process (nframes_t transport_frame, nframes_t nframes, nframes_t
                size_t num_events = _source_port->get_midi_buffer().size();
                size_t to_write = std::min(_capture_buf->write_space(), num_events);
 
+               MidiBuffer::iterator port_iter = _source_port->get_midi_buffer().begin();
+
                for (size_t i=0; i < to_write; ++i) {
-                       MidiEvent& ev = _source_port->get_midi_buffer()[i];
-                       _capture_buf->write(ev.time + transport_frame, ev.size, ev.buffer);
+                       const MidiEvent& ev = *port_iter;
+                       _capture_buf->write(ev.time() + transport_frame, ev.size(), ev.buffer());
+                       ++port_iter;
                }
        
        } else {
@@ -596,7 +603,7 @@ MidiDiskstream::process (nframes_t transport_frame, nframes_t nframes, nframes_t
 
                // XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX
                // Write into playback buffer here, and whatnot?
-               cerr << "MDS FIXME: collect playback" << endl;
+               //cerr << "MDS FIXME: collect playback" << endl;
 
        }
 
@@ -663,6 +670,7 @@ MidiDiskstream::set_pending_overwrite (bool yn)
 int
 MidiDiskstream::overwrite_existing_buffers ()
 {
+       cerr << "MDS: overwrite_existing_buffers() (does nothing)" << endl;
        return 0;
 }
 
@@ -671,6 +679,8 @@ MidiDiskstream::seek (nframes_t frame, bool complete_refill)
 {
        Glib::Mutex::Lock lm (state_lock);
        int ret = -1;
+       
+       //cerr << "MDS: seek: " << frame << endl;
 
        _playback_buf->reset();
        _capture_buf->reset();
@@ -700,6 +710,8 @@ MidiDiskstream::can_internal_playback_seek (nframes_t distance)
 int
 MidiDiskstream::internal_playback_seek (nframes_t distance)
 {
+       cerr << "MDS: internal_playback_seek " << distance << endl;
+
        first_recordable_frame += distance;
        playback_sample += distance;
 
@@ -813,18 +825,6 @@ MidiDiskstream::do_refill ()
                return 0;
        }
 
-       /* if there are 2+ chunks of disk i/o possible for
-          this track, let the caller know so that it can arrange
-          for us to be called again, ASAP.
-          */
-
-       // FIXME: using disk_io_chunk_frames as an event count, not good
-       // count vs duration semantic differences are nonexistant for audio,
-       // which makes translating for MIDI code confusing...
-       if (_playback_buf->write_space() >= (_slaved?3:2) * disk_io_chunk_frames) {
-               ret = 1;
-       }
-
        /* if we're running close to normal speed and there isn't enough 
           space to do disk_io_chunk_frames of I/O, then don't bother.  
 
@@ -833,7 +833,7 @@ MidiDiskstream::do_refill ()
           */
 
        if ((write_space < disk_io_chunk_frames) && fabs (_actual_speed) < 2.0f) {
-               cerr << "No refill 1\n";
+               //cerr << "No refill 1\n";
                return 0;
        }
 
@@ -843,12 +843,12 @@ MidiDiskstream::do_refill ()
           */
 
        if (_slaved && write_space < (_playback_buf->capacity() / 2)) {
-               cerr << "No refill 2\n";
+               //cerr << "No refill 2\n";
                return 0;
        }
 
        if (reversed) {
-               cerr << "No refill 3 (reverse)\n";
+               //cerr << "No refill 3 (reverse)\n";
                return 0;
        }
 
@@ -860,26 +860,10 @@ MidiDiskstream::do_refill ()
                return 0;
        }
 
-#if 0
-       // or this
-       if (file_frame > max_frames - total_space) {
-
-               /* to close to the end: read what we can, and zero fill the rest */
-
-               zero_fill = total_space - (max_frames - file_frame);
-               total_space = max_frames - file_frame;
-
-       } else {
-               zero_fill = 0;
-       }
-#endif
-
-       // At this point we:
+       // At this point we...
        assert(_playback_buf->write_space() > 0); // ... have something to write to, and
        assert(file_frame <= max_frames); // ... something to write
 
-       // So (read it, then) write it:
-       
        nframes_t file_frame_tmp = file_frame;
        nframes_t to_read = min(disk_io_chunk_frames, (max_frames - file_frame));
        
@@ -1023,7 +1007,7 @@ MidiDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_cap
                /* figure out the name for this take */
        
                srcs.push_back (_write_source);
-               _write_source->update_header (capture_info.front()->start, when, twhen);
+               _write_source->set_timeline_position (capture_info.front()->start);
                _write_source->set_captured_for (_name);
 
                string whole_file_region_name;
@@ -1106,6 +1090,35 @@ MidiDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_cap
        capture_start_frame = 0;
 }
 
+void
+MidiDiskstream::transport_looped (nframes_t transport_frame)
+{
+       if (was_recording) {
+
+               // adjust the capture length knowing that the data will be recorded to disk
+               // only necessary after the first loop where we're recording
+               if (capture_info.size() == 0) {
+                       capture_captured += _capture_offset;
+
+                       if (_alignment_style == ExistingMaterial) {
+                               capture_captured += _session.worst_output_latency();
+                       } else {
+                               capture_captured += _roll_delay;
+                       }
+               }
+
+               finish_capture (true);
+
+               // the next region will start recording via the normal mechanism
+               // we'll set the start position to the current transport pos
+               // no latency adjustment or capture offset needs to be made, as that already happened the first time
+               capture_start_frame = transport_frame;
+               first_recordable_frame = transport_frame; // mild lie
+               last_recordable_frame = max_frames;
+               was_recording = true;
+       }
+}
+
 void
 MidiDiskstream::finish_capture (bool rec_monitors_input)
 {
@@ -1180,6 +1193,12 @@ MidiDiskstream::engage_record_enable ()
                _source_port->request_monitor_input (!(Config->get_auto_input() && rolling));
        }
 
+       // FIXME: Why is this necessary?  Isn't needed for AudioDiskstream...
+       if (!_write_source)
+               use_new_write_source();
+
+       _write_source->mark_streaming_midi_write_started (_note_mode, _session.transport_frame());
+
        RecordEnableChanged (); /* EMIT SIGNAL */
 }
 
@@ -1344,7 +1363,7 @@ MidiDiskstream::use_new_write_source (uint32_t n)
 
        if (_write_source) {
 
-               if (SMFSource::is_empty (_write_source->path())) {
+               if (_write_source->is_empty ()) {
                        _write_source->mark_for_remove ();
                        _write_source.reset();
                } else {
@@ -1380,6 +1399,7 @@ MidiDiskstream::reset_write_sources (bool mark_write_complete, bool force)
        if (_write_source && mark_write_complete) {
                _write_source->mark_streaming_write_completed ();
        }
+
        use_new_write_source (0);
                        
        if (record_enabled()) {
@@ -1469,9 +1489,8 @@ MidiDiskstream::get_playback(MidiBuffer& dst, nframes_t start, nframes_t end)
        dst.clear();
        assert(dst.size() == 0);
        
-       // I think this happens with reverse varispeed?  maybe?
+       // Reverse.  ... We just don't do reverse, ok?  Back off.
        if (end <= start) {
-               cerr << "MDS: Reverse?  Skipping" << endl;
                return;
        }