13
0

send sustain=off and all-notes-off when a MIDI track is muted (may fix #4295)

git-svn-id: svn://localhost/ardour2/branches/3.0@11005 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis 2011-12-14 17:17:30 +00:00
parent 60872a8504
commit 96585e532c
6 changed files with 51 additions and 8 deletions

View File

@ -117,6 +117,8 @@ protected:
bool should_monitor () const;
bool send_silence () const;
void act_on_mute ();
private:
virtual boost::shared_ptr<Diskstream> diskstream_factory (XMLNode const &);

View File

@ -140,7 +140,7 @@ class Route : public SessionObject, public Automatable, public RouteGroupMember,
bool muted () const;
void set_mute (bool yn, void* src);
/* controls use set_solo() to modify this route's solo state
*/
@ -468,6 +468,8 @@ class Route : public SessionObject, public Automatable, public RouteGroupMember,
boost::shared_ptr<MuteControllable> _mute_control;
boost::shared_ptr<MuteMaster> _mute_master;
virtual void act_on_mute () {}
std::string _comment;
bool _have_internal_generator;
bool _solo_safe;

View File

@ -128,20 +128,16 @@ MidiPort::cycle_split ()
void
MidiPort::resolve_notes (void* jack_buffer, MidiBuffer::TimeType when)
{
uint8_t ev[3];
ev[2] = 0;
for (uint8_t channel = 0; channel <= 0xF; channel++) {
ev[0] = (MIDI_CMD_CONTROL | channel);
uint8_t ev[3] = { MIDI_CMD_CONTROL | channel, MIDI_CTL_SUSTAIN, 0 };
/* we need to send all notes off AND turn the
* sustain/damper pedal off to handle synths
* that prioritize sustain over AllNotesOff
*/
ev[1] = MIDI_CTL_SUSTAIN;
if (jack_midi_event_write (jack_buffer, when, ev, 3) != 0) {
cerr << "failed to deliver sustain-zero on channel " << channel << " on port " << name() << endl;
}
@ -164,7 +160,7 @@ MidiPort::flush_buffers (pframes_t nframes, framepos_t /*time*/)
if (_resolve_required) {
/* resolve all notes at the start of the buffer */
resolve_notes (jack_buffer, 0);
_resolve_required= false;
_resolve_required = false;
}
for (MidiBuffer::iterator i = _buffer->begin(); i != _buffer->end(); ++i) {

View File

@ -85,6 +85,14 @@ MidiStateTracker::track (const MidiBuffer::iterator &from, const MidiBuffer::ite
continue;
}
/* catch AllNotesOff message and turn off all notes
*/
if (ev.type() == MIDI_CTL_ALL_NOTES_OFF) {
cerr << "State tracker sees ALL_NOTES_OFF, silenceing " << sizeof (_active_notes) << endl;
memset (_active_notes, 0, sizeof (_active_notes));
}
track_note_onoffs (ev);
}
}

View File

@ -715,3 +715,33 @@ 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);
}
}
}
}

View File

@ -805,6 +805,11 @@ Route::set_mute (bool yn, void *src)
if (muted() != yn) {
_mute_master->set_muted_by_self (yn);
/* allow any derived classes to respond to the mute change
before anybody else knows about it.
*/
act_on_mute ();
/* tell everyone else */
mute_changed (src); /* EMIT SIGNAL */
_mute_control->Changed (); /* EMIT SIGNAL */
}