summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2011-12-14 17:17:30 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2011-12-14 17:17:30 +0000
commit96585e532c879220057edd050806c823ed6e4c1d (patch)
treef476498ed64726e8196167cd278e35803da91ab0
parent60872a8504cccc0d7e6c2485af8c0362577f5723 (diff)
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
-rw-r--r--libs/ardour/ardour/midi_track.h2
-rw-r--r--libs/ardour/ardour/route.h4
-rw-r--r--libs/ardour/midi_port.cc10
-rw-r--r--libs/ardour/midi_state_tracker.cc8
-rw-r--r--libs/ardour/midi_track.cc30
-rw-r--r--libs/ardour/route.cc5
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> 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<MuteControllable> _mute_control;
boost::shared_ptr<MuteMaster> _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<<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);
+ }
+ }
+ }
+}
+
diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc
index 46bc9b7696..c97421a472 100644
--- a/libs/ardour/route.cc
+++ b/libs/ardour/route.cc
@@ -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 */
}