From 96585e532c879220057edd050806c823ed6e4c1d Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Wed, 14 Dec 2011 17:17:30 +0000 Subject: [PATCH] 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 --- libs/ardour/ardour/midi_track.h | 2 ++ libs/ardour/ardour/route.h | 4 +++- libs/ardour/midi_port.cc | 10 +++------- libs/ardour/midi_state_tracker.cc | 8 ++++++++ libs/ardour/midi_track.cc | 30 ++++++++++++++++++++++++++++++ libs/ardour/route.cc | 5 +++++ 6 files changed, 51 insertions(+), 8 deletions(-) diff --git a/libs/ardour/ardour/midi_track.h b/libs/ardour/ardour/midi_track.h index 1f2f11b5bc..018b5c4f60 100644 --- a/libs/ardour/ardour/midi_track.h +++ b/libs/ardour/ardour/midi_track.h @@ -117,6 +117,8 @@ protected: bool should_monitor () const; bool send_silence () const; + void act_on_mute (); + private: virtual boost::shared_ptr diskstream_factory (XMLNode const &); diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h index 2df8ce4414..7d93c0c68b 100644 --- a/libs/ardour/ardour/route.h +++ b/libs/ardour/ardour/route.h @@ -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 _mute_control; boost::shared_ptr _mute_master; + virtual void act_on_mute () {} + std::string _comment; bool _have_internal_generator; bool _solo_safe; diff --git a/libs/ardour/midi_port.cc b/libs/ardour/midi_port.cc index 50d4ce64e8..9383bb237b 100644 --- a/libs/ardour/midi_port.cc +++ b/libs/ardour/midi_port.cc @@ -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) { diff --git a/libs/ardour/midi_state_tracker.cc b/libs/ardour/midi_state_tracker.cc index f5020e08a7..342d9d0e58 100644 --- a/libs/ardour/midi_state_tracker.cc +++ b/libs/ardour/midi_state_tracker.cc @@ -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); } } diff --git a/libs/ardour/midi_track.cc b/libs/ardour/midi_track.cc index 3033f3d952..e835008e67 100644 --- a/libs/ardour/midi_track.cc +++ b/libs/ardour/midi_track.cc @@ -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<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 */ }