make switching between input+disk monitoring work "right" for MIDI tracks; also fix a bug that led to messages about notes already being on at program start because of a double seek with no read in between
git-svn-id: svn://localhost/ardour2/branches/3.0@12762 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
88dfe91ce3
commit
a8237f1aed
|
@ -63,6 +63,7 @@ class MidiDiskstream : public Diskstream
|
|||
float capture_buffer_load() const;
|
||||
|
||||
void get_playback (MidiBuffer& dst, framecnt_t);
|
||||
void flush_playback (framepos_t, framepos_t);
|
||||
|
||||
void set_record_enabled (bool yn);
|
||||
|
||||
|
|
|
@ -45,6 +45,7 @@ class MidiPort : public Port {
|
|||
void transport_stopped ();
|
||||
void realtime_locate ();
|
||||
void reset ();
|
||||
void require_resolve ();
|
||||
|
||||
bool input_active() const { return _input_active; }
|
||||
void set_input_active (bool yn);
|
||||
|
|
|
@ -55,6 +55,7 @@ public:
|
|||
|
||||
size_t read(MidiBuffer& dst, framepos_t start, framepos_t end, framecnt_t offset=0, bool stop_on_overflow_in_destination=false);
|
||||
void dump(std::ostream& dst);
|
||||
void flush (framepos_t start, framepos_t end);
|
||||
|
||||
/** Set the channel filtering mode.
|
||||
* @param mask If mode is FilterChannels, each bit represents a midi channel:
|
||||
|
|
|
@ -506,6 +506,14 @@ MidiDiskstream::seek (framepos_t frame, bool complete_refill)
|
|||
Glib::Mutex::Lock lm (state_lock);
|
||||
int ret = -1;
|
||||
|
||||
if (g_atomic_int_get (&_frames_read_from_ringbuffer) == 0) {
|
||||
/* we haven't read anything since the last seek,
|
||||
so flush all note trackers to prevent
|
||||
wierdness
|
||||
*/
|
||||
reset_tracker ();
|
||||
}
|
||||
|
||||
_playback_buf->reset();
|
||||
_capture_buf->reset();
|
||||
g_atomic_int_set(&_frames_read_from_ringbuffer, 0);
|
||||
|
@ -1269,6 +1277,13 @@ MidiDiskstream::use_pending_capture_data (XMLNode& /*node*/)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
MidiDiskstream::flush_playback (framepos_t start, framepos_t end)
|
||||
{
|
||||
_playback_buf->flush (start, end);
|
||||
g_atomic_int_add (&_frames_read_from_ringbuffer, end - start);
|
||||
}
|
||||
|
||||
/** Writes playback events from playback_sample for nframes to dst, translating time stamps
|
||||
* so that an event at playback_sample has time = 0
|
||||
*/
|
||||
|
|
|
@ -188,6 +188,12 @@ MidiPort::flush_buffers (pframes_t nframes)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
MidiPort::require_resolve ()
|
||||
{
|
||||
_resolve_required = true;
|
||||
}
|
||||
|
||||
void
|
||||
MidiPort::transport_stopped ()
|
||||
{
|
||||
|
|
|
@ -98,7 +98,9 @@ MidiRingBuffer<T>::read(MidiBuffer& dst, framepos_t start, framepos_t end, frame
|
|||
break;
|
||||
} else if (ev_time + loop_offset < start) {
|
||||
DEBUG_TRACE (DEBUG::MidiDiskstreamIO, string_compose ("MRB event @ %1 before start @ %2\n", ev_time, start));
|
||||
break;
|
||||
this->increment_read_ptr (prefix_size);
|
||||
this->increment_read_ptr (ev_size);
|
||||
continue;
|
||||
} else {
|
||||
DEBUG_TRACE (DEBUG::MidiDiskstreamIO, string_compose ("MRB event @ %1 in range %2 .. %3\n", ev_time, start, end));
|
||||
}
|
||||
|
@ -193,6 +195,36 @@ MidiRingBuffer<T>::read(MidiBuffer& dst, framepos_t start, framepos_t end, frame
|
|||
return count;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
MidiRingBuffer<T>::flush (framepos_t start, framepos_t end)
|
||||
{
|
||||
const size_t prefix_size = sizeof(T) + sizeof(Evoral::EventType) + sizeof(uint32_t);
|
||||
|
||||
while (this->read_space() >= prefix_size) {
|
||||
uint8_t peekbuf[prefix_size];
|
||||
bool success;
|
||||
uint32_t ev_size;
|
||||
T ev_time;
|
||||
|
||||
success = this->peek (peekbuf, prefix_size);
|
||||
/* this cannot fail, because we've already verified that there
|
||||
is prefix_space to read
|
||||
*/
|
||||
assert (success);
|
||||
|
||||
ev_time = *((T*) peekbuf);
|
||||
|
||||
if (ev_time >= end) {
|
||||
break;
|
||||
}
|
||||
|
||||
ev_size = *((uint32_t*)(peekbuf + sizeof(T) + sizeof (Evoral::EventType)));
|
||||
this->increment_read_ptr (prefix_size);
|
||||
this->increment_read_ptr (ev_size);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
MidiRingBuffer<T>::dump(ostream& str)
|
||||
|
|
|
@ -309,6 +309,7 @@ MidiTrack::roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame
|
|||
return dret;
|
||||
}
|
||||
|
||||
|
||||
_silent = false;
|
||||
|
||||
if ((dret = diskstream->process (transport_frame, nframes, playback_distance)) != 0) {
|
||||
|
@ -329,9 +330,18 @@ MidiTrack::roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame
|
|||
at least potentially (depending on monitoring options)
|
||||
*/
|
||||
|
||||
/* because the playback buffer is event based and not a
|
||||
* continuous stream, we need to make sure that we empty
|
||||
* it of events every cycle to avoid it filling up with events
|
||||
* read from disk, while we are actually monitoring input
|
||||
*/
|
||||
|
||||
diskstream->flush_playback (start_frame, end_frame);
|
||||
|
||||
passthru (start_frame, end_frame, nframes, 0);
|
||||
|
||||
} else {
|
||||
|
||||
/*
|
||||
XXX is it true that the earlier test on n_outputs()
|
||||
means that we can avoid checking it again here? i think
|
||||
|
@ -343,7 +353,6 @@ MidiTrack::roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame
|
|||
|
||||
/* copy the diskstream data to all output buffers */
|
||||
|
||||
//const size_t limit = n_process_buffers().n_audio();
|
||||
BufferSet& bufs = _session.get_scratch_buffers (n_process_buffers());
|
||||
MidiBuffer& mbuf (bufs.get_midi (0));
|
||||
|
||||
|
@ -735,12 +744,28 @@ MidiTrack::act_on_mute ()
|
|||
void
|
||||
MidiTrack::set_monitoring (MonitorChoice mc)
|
||||
{
|
||||
Track::set_monitoring (mc);
|
||||
if (mc != _monitoring) {
|
||||
|
||||
boost::shared_ptr<MidiDiskstream> md (midi_diskstream());
|
||||
Track::set_monitoring (mc);
|
||||
|
||||
/* monitoring state changed, so flush out any on notes at the
|
||||
* port level.
|
||||
*/
|
||||
|
||||
if (md) {
|
||||
md->reset_tracker ();
|
||||
PortSet& ports (_output->ports());
|
||||
|
||||
for (PortSet::iterator p = ports.begin(); p != ports.end(); ++p) {
|
||||
boost::shared_ptr<MidiPort> mp = boost::dynamic_pointer_cast<MidiPort> (*p);
|
||||
if (mp) {
|
||||
mp->require_resolve ();
|
||||
}
|
||||
}
|
||||
|
||||
boost::shared_ptr<MidiDiskstream> md (midi_diskstream());
|
||||
|
||||
if (md) {
|
||||
md->reset_tracker ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user