InstrumentTrack::~InstrumentTrack() { // kill all running notes and the iph silenceAllNotes( true ); // now we're save deleting the instrument if( m_instrument ) delete m_instrument; }
InstrumentTrack::~InstrumentTrack() { // kill all running notes silenceAllNotes(); // now we're save deleting the instrument delete m_instrument; }
InstrumentTrack::~InstrumentTrack() { // kill all running notes silenceAllNotes(); engine::getMixer()->removePlayHandles( this ); // now we're save deleting the instrument delete m_instrument; }
Instrument * InstrumentTrack::loadInstrument( const QString & _plugin_name ) { silenceAllNotes(); engine::getMixer()->lock(); delete m_instrument; m_instrument = Instrument::instantiate( _plugin_name, this ); engine::getMixer()->unlock(); emit instrumentChanged(); return m_instrument; }
Instrument * InstrumentTrack::loadInstrument( const QString & _plugin_name ) { silenceAllNotes( true ); lock(); delete m_instrument; m_instrument = Instrument::instantiate( _plugin_name, this ); unlock(); setName( m_instrument->displayName() ); emit instrumentChanged(); return m_instrument; }
void InstrumentTrack::loadTrackSpecificSettings( const QDomElement & _this ) { silenceAllNotes(); engine::getMixer()->lock(); m_volumeModel.loadSettings( _this, "vol" ); // compat-hacks - move to mmp::upgrade if( _this.hasAttribute( "surpos" ) || _this.hasAttribute( "surpos-x" ) || !_this.firstChildElement( "automationpattern" ). firstChildElement( "surpos-x" ).isNull() ) { surroundAreaModel m( this, this ); m.loadSettings( _this, "surpos" ); m_panningModel.setValue( m.x() * 100 / SURROUND_AREA_SIZE ); } else { m_panningModel.loadSettings( _this, "pan" ); } m_pitchRangeModel.loadSettings( _this, "pitchrange" ); m_pitchModel.loadSettings( _this, "pitch" ); m_effectChannelModel.loadSettings( _this, "fxch" ); if( _this.hasAttribute( "baseoct" ) ) { // TODO: move this compat code to mmp.cpp -> upgrade() baseNoteModel()->setInitValue( _this. attribute( "baseoct" ).toInt() * KeysPerOctave + _this.attribute( "basetone" ).toInt() ); } else { baseNoteModel()->loadSettings( _this, "basenote" ); } // clear effect-chain just in case we load an old preset without FX-data m_audioPort.effects()->clear(); QDomNode node = _this.firstChild(); while( !node.isNull() ) { if( node.isElement() ) { if( m_soundShaping.nodeName() == node.nodeName() ) { m_soundShaping.restoreState( node.toElement() ); } else if( m_chordCreator.nodeName() == node.nodeName() ) { m_chordCreator.restoreState( node.toElement() ); } else if( m_arpeggiator.nodeName() == node.nodeName() ) { m_arpeggiator.restoreState( node.toElement() ); } else if( m_midiPort.nodeName() == node.nodeName() ) { m_midiPort.restoreState( node.toElement() ); } else if( m_audioPort.effects()->nodeName() == node.nodeName() ) { m_audioPort.effects()->restoreState( node.toElement() ); } else if( node.nodeName() == "instrument" ) { delete m_instrument; m_instrument = NULL; m_instrument = Instrument::instantiate( node.toElement().attribute( "name" ), this ); m_instrument->restoreState( node.firstChildElement() ); emit instrumentChanged(); } // compat code - if node-name doesn't match any known // one, we assume that it is an instrument-plugin // which we'll try to load else if( AutomationPattern::classNodeName() != node.nodeName() && ControllerConnection::classNodeName() != node.nodeName() && !node.toElement().hasAttribute( "id" ) ) { delete m_instrument; m_instrument = NULL; m_instrument = Instrument::instantiate( node.nodeName(), this ); if( m_instrument->nodeName() == node.nodeName() ) { m_instrument->restoreState( node.toElement() ); } emit instrumentChanged(); } } node = node.nextSibling(); } engine::getMixer()->unlock(); }
void InstrumentTrack::loadTrackSpecificSettings( const QDomElement & thisElement ) { silenceAllNotes( true ); lock(); m_volumeModel.loadSettings( thisElement, "vol" ); m_panningModel.loadSettings( thisElement, "pan" ); m_pitchRangeModel.loadSettings( thisElement, "pitchrange" ); m_pitchModel.loadSettings( thisElement, "pitch" ); m_effectChannelModel.setRange( 0, Engine::fxMixer()->numChannels()-1 ); m_effectChannelModel.loadSettings( thisElement, "fxch" ); m_baseNoteModel.loadSettings( thisElement, "basenote" ); m_useMasterPitchModel.loadSettings( thisElement, "usemasterpitch"); // clear effect-chain just in case we load an old preset without FX-data m_audioPort.effects()->clear(); QDomNode node = thisElement.firstChild(); while( !node.isNull() ) { if( node.isElement() ) { if( m_soundShaping.nodeName() == node.nodeName() ) { m_soundShaping.restoreState( node.toElement() ); } else if( m_noteStacking.nodeName() == node.nodeName() ) { m_noteStacking.restoreState( node.toElement() ); } else if( m_arpeggio.nodeName() == node.nodeName() ) { m_arpeggio.restoreState( node.toElement() ); } else if( m_midiPort.nodeName() == node.nodeName() ) { m_midiPort.restoreState( node.toElement() ); } else if( m_audioPort.effects()->nodeName() == node.nodeName() ) { m_audioPort.effects()->restoreState( node.toElement() ); } else if( node.nodeName() == "instrument" ) { delete m_instrument; m_instrument = NULL; m_instrument = Instrument::instantiate( node.toElement().attribute( "name" ), this ); m_instrument->restoreState( node.firstChildElement() ); emit instrumentChanged(); } // compat code - if node-name doesn't match any known // one, we assume that it is an instrument-plugin // which we'll try to load else if( AutomationPattern::classNodeName() != node.nodeName() && ControllerConnection::classNodeName() != node.nodeName() && !node.toElement().hasAttribute( "id" ) ) { delete m_instrument; m_instrument = NULL; m_instrument = Instrument::instantiate( node.nodeName(), this ); if( m_instrument->nodeName() == node.nodeName() ) { m_instrument->restoreState( node.toElement() ); } emit instrumentChanged(); } } node = node.nextSibling(); } updatePitchRange(); unlock(); }
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() ); } }