From 97680e081efe93059930b43dd9a901b8c72b10d7 Mon Sep 17 00:00:00 2001 From: IanCaio Date: Mon, 1 Jun 2020 22:48:34 -0300 Subject: [PATCH] Allows instruments to keep the MIDI channel information when forwarding (#5470) Now it's possible to forward received MIDI events with their original channel, either to another track or to the instrument plugin itself. To do that, the user must select the channel "--" on the MIDI output widget. In that case, all MIDI events will be forwarded with their original channel, and the MIDI events produced by the track itself will be sent with the default channel. --- include/MidiPort.h | 5 ++++- src/core/midi/MidiPort.cpp | 7 ++++--- src/gui/widgets/InstrumentMidiIOView.cpp | 4 +--- src/tracks/InstrumentTrack.cpp | 12 +++++++++--- 4 files changed, 18 insertions(+), 10 deletions(-) diff --git a/include/MidiPort.h b/include/MidiPort.h index e9cba39ed..acf95992f 100644 --- a/include/MidiPort.h +++ b/include/MidiPort.h @@ -96,7 +96,10 @@ public: int realOutputChannel() const { - return outputChannel() - 1; + // There's a possibility of outputChannel being 0 ("--"), which is used to keep all + // midi channels when forwarding. In that case, realOutputChannel will return the + // default channel 1 (whose value is 0). + return outputChannel() ? outputChannel() - 1 : 0; } void processInEvent( const MidiEvent& event, const MidiTime& time = MidiTime() ); diff --git a/src/core/midi/MidiPort.cpp b/src/core/midi/MidiPort.cpp index 52e0a5223..4e97a6713 100644 --- a/src/core/midi/MidiPort.cpp +++ b/src/core/midi/MidiPort.cpp @@ -47,7 +47,7 @@ MidiPort::MidiPort( const QString& name, m_midiEventProcessor( eventProcessor ), m_mode( mode ), m_inputChannelModel( 0, 0, MidiChannelCount, this, tr( "Input channel" ) ), - m_outputChannelModel( 1, 1, MidiChannelCount, this, tr( "Output channel" ) ), + m_outputChannelModel( 1, 0, MidiChannelCount, this, tr( "Output channel" ) ), m_inputControllerModel( 0, 0, MidiControllerCount, this, tr( "Input controller" ) ), m_outputControllerModel( 0, 0, MidiControllerCount, this, tr( "Output controller" ) ), m_fixedInputVelocityModel( -1, -1, MidiMaxVelocity, this, tr( "Fixed input velocity" ) ), @@ -151,8 +151,9 @@ void MidiPort::processInEvent( const MidiEvent& event, const MidiTime& time ) void MidiPort::processOutEvent( const MidiEvent& event, const MidiTime& time ) { - // mask event - if( isOutputEnabled() && realOutputChannel() == event.channel() ) + // When output is enabled, route midi events if the selected channel matches + // the event channel or if there's no selected channel (value 0, represented by "--") + if( isOutputEnabled() && ( outputChannel() == 0 || realOutputChannel() == event.channel() ) ) { MidiEvent outEvent = event; diff --git a/src/gui/widgets/InstrumentMidiIOView.cpp b/src/gui/widgets/InstrumentMidiIOView.cpp index 56047d5e6..62d1dbb18 100644 --- a/src/gui/widgets/InstrumentMidiIOView.cpp +++ b/src/gui/widgets/InstrumentMidiIOView.cpp @@ -84,8 +84,8 @@ InstrumentMidiIOView::InstrumentMidiIOView( QWidget* parent ) : midiOutputLayout->setSpacing( 6 ); m_outputChannelSpinBox = new LcdSpinBox( 2, m_midiOutputGroupBox ); + m_outputChannelSpinBox->addTextForValue( 0, "--" ); m_outputChannelSpinBox->setLabel( tr( "CHANNEL" ) ); - m_outputChannelSpinBox->setEnabled( false ); midiOutputLayout->addWidget( m_outputChannelSpinBox ); m_fixedOutputVelocitySpinBox = new LcdSpinBox( 3, m_midiOutputGroupBox ); @@ -108,8 +108,6 @@ InstrumentMidiIOView::InstrumentMidiIOView( QWidget* parent ) : midiOutputLayout->addWidget( m_fixedOutputNoteSpinBox ); midiOutputLayout->addStretch(); - connect( m_midiOutputGroupBox->ledButton(), SIGNAL( toggled( bool ) ), - m_outputChannelSpinBox, SLOT( setEnabled( bool ) ) ); connect( m_midiOutputGroupBox->ledButton(), SIGNAL( toggled( bool ) ), m_fixedOutputVelocitySpinBox, SLOT( setEnabled( bool ) ) ); connect( m_midiOutputGroupBox->ledButton(), SIGNAL( toggled( bool ) ), diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index 18dcdf81a..8ed7d2b85 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -393,6 +393,12 @@ void InstrumentTrack::processOutEvent( const MidiEvent& event, const MidiTime& t const MidiEvent transposedEvent = applyMasterKey( event ); const int key = transposedEvent.key(); + // If we have a selected output midi channel between 1-16, we will use that channel to handle the midi event. + // But if our selected midi output channel is 0 ("--"), we will use the event channel instead. + const auto handleEventOutputChannel = midiPort()->outputChannel() == 0 + ? event.channel() + : midiPort()->realOutputChannel(); + switch( event.type() ) { case MidiNoteOn: @@ -403,10 +409,10 @@ void InstrumentTrack::processOutEvent( const MidiEvent& event, const MidiTime& t { if( m_runningMidiNotes[key] > 0 ) { - m_instrument->handleMidiEvent( MidiEvent( MidiNoteOff, midiPort()->realOutputChannel(), key, 0 ), time, offset ); + m_instrument->handleMidiEvent( MidiEvent( MidiNoteOff, handleEventOutputChannel, key, 0 ), time, offset ); } ++m_runningMidiNotes[key]; - m_instrument->handleMidiEvent( MidiEvent( MidiNoteOn, midiPort()->realOutputChannel(), key, event.velocity() ), time, offset ); + m_instrument->handleMidiEvent( MidiEvent( MidiNoteOn, handleEventOutputChannel, key, event.velocity() ), time, offset ); } m_midiNotesMutex.unlock(); @@ -419,7 +425,7 @@ void InstrumentTrack::processOutEvent( const MidiEvent& event, const MidiTime& t if( key >= 0 && key < NumKeys && --m_runningMidiNotes[key] <= 0 ) { - m_instrument->handleMidiEvent( MidiEvent( MidiNoteOff, midiPort()->realOutputChannel(), key, 0 ), time, offset ); + m_instrument->handleMidiEvent( MidiEvent( MidiNoteOff, handleEventOutputChannel, key, 0 ), time, offset ); } m_midiNotesMutex.unlock(); emit endNote();