void InstrumentTrack::processInEvent( const MidiEvent& event, const MidiTime& time, f_cnt_t offset ) { bool eventHandled = false; switch( event.type() ) { // we don't send MidiNoteOn, MidiNoteOff and MidiKeyPressure // events to instrument as NotePlayHandle will send them on its // own case MidiNoteOn: if( event.velocity() > 0 ) { NotePlayHandle* nph; m_notesMutex.lock(); if( m_notes[event.key()] == NULL ) { nph = NotePlayHandleManager::acquire( this, offset, typeInfo<f_cnt_t>::max() / 2, Note( MidiTime(), MidiTime(), event.key(), event.volume( midiPort()->baseVelocity() ) ), NULL, event.channel(), NotePlayHandle::OriginMidiInput ); m_notes[event.key()] = nph; if( ! Engine::mixer()->addPlayHandle( nph ) ) { m_notes[event.key()] = NULL; } } m_notesMutex.unlock(); eventHandled = true; break; } case MidiNoteOff: m_notesMutex.lock(); if( m_notes[event.key()] != NULL ) { // do actual note off and remove internal reference to NotePlayHandle (which itself will // be deleted later automatically) m_notes[event.key()]->noteOff( offset ); m_notes[event.key()] = NULL; } m_notesMutex.unlock(); eventHandled = true; break; case MidiKeyPressure: if( m_notes[event.key()] != NULL ) { // setVolume() calls processOutEvent() with MidiKeyPressure so the // attached instrument will receive the event as well m_notes[event.key()]->setVolume( event.volume( midiPort()->baseVelocity() ) ); } eventHandled = true; break; case MidiPitchBend: // updatePitch() is connected to m_pitchModel::dataChanged() which will send out // MidiPitchBend events m_pitchModel.setValue( m_pitchModel.minValue() + event.pitchBend() * m_pitchModel.range() / MidiMaxPitchBend ); break; case MidiControlChange: if( event.controllerNumber() == MidiControllerSustain ) { if( event.controllerValue() > MidiMaxControllerValue/2 ) { m_sustainPedalPressed = true; } else { m_sustainPedalPressed = false; } } if( event.controllerNumber() == MidiControllerAllSoundOff || event.controllerNumber() == MidiControllerAllNotesOff || event.controllerNumber() == MidiControllerOmniOn || event.controllerNumber() == MidiControllerOmniOff || event.controllerNumber() == MidiControllerMonoOn || event.controllerNumber() == MidiControllerPolyOn ) { silenceAllNotes(); } break; case MidiMetaEvent: // handle special cases such as note panning switch( event.metaEvent() ) { case MidiNotePanning: if( m_notes[event.key()] != NULL ) { eventHandled = true; m_notes[event.key()]->setPanning( event.panning() ); } break; default: qWarning( "InstrumentTrack: unhandled MIDI meta event: %i", event.metaEvent() ); break; } break; default: break; } if( eventHandled == false && instrument()->handleMidiEvent( event, time, offset ) == false ) { qWarning( "InstrumentTrack: unhandled MIDI event %d", event.type() ); } }