/* * InstrumentTrack.h - declaration of class InstrumentTrack, a track + window * which holds an instrument-plugin * * Copyright (c) 2004-2014 Tobias Doerffel * * This file is part of LMMS - http://lmms.io * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program (see COPYING); if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA. * */ #ifndef INSTRUMENT_TRACK_H #define INSTRUMENT_TRACK_H #include "AudioPort.h" #include "InstrumentFunctions.h" #include "InstrumentSoundShaping.h" #include "MidiEventProcessor.h" #include "MidiPort.h" #include "NotePlayHandle.h" #include "Piano.h" #include "PianoView.h" #include "Pitch.h" #include "Track.h" class QLineEdit; template class QQueue; class InstrumentFunctionArpeggioView; class InstrumentFunctionNoteStackingView; class EffectRackView; class InstrumentSoundShapingView; class FadeButton; class Instrument; class InstrumentTrackWindow; class InstrumentMidiIOView; class InstrumentMiscView; class Knob; class LcdSpinBox; class LeftRightNav; class midiPortMenu; class DataFile; class PluginView; class TabWidget; class TrackLabelButton; class LedCheckBox; class EXPORT InstrumentTrack : public Track, public MidiEventProcessor { Q_OBJECT MM_OPERATORS mapPropertyFromModel(int,getVolume,setVolume,m_volumeModel); public: InstrumentTrack( TrackContainer* tc ); virtual ~InstrumentTrack(); // used by instrument void processAudioBuffer( sampleFrame * _buf, const fpp_t _frames, NotePlayHandle * _n ); MidiEvent applyMasterKey( const MidiEvent& event ); virtual void processInEvent( const MidiEvent& event, const MidiTime& time = MidiTime(), f_cnt_t offset = 0 ); virtual void processOutEvent( const MidiEvent& event, const MidiTime& time = MidiTime(), f_cnt_t offset = 0 ); // silence all running notes played by this track void silenceAllNotes( bool removeIPH = false ); bool isSustainPedalPressed() const { return m_sustainPedalPressed; } f_cnt_t beatLen( NotePlayHandle * _n ) const; // for capturing note-play-events -> need that for arpeggio, // filter and so on void playNote( NotePlayHandle * _n, sampleFrame * _working_buffer ); QString instrumentName() const; const Instrument *instrument() const { return m_instrument; } Instrument *instrument() { return m_instrument; } void deleteNotePluginData( NotePlayHandle * _n ); // name-stuff virtual void setName( const QString & _new_name ); // translate given key of a note-event to absolute key (i.e. // add global master-pitch and base-note of this instrument track) int masterKey( int _midi_key ) const; // translate pitch to midi-pitch [0,16383] int midiPitch() const { return static_cast( ( ( m_pitchModel.value() + m_pitchModel.range()/2 ) * MidiMaxPitchBend ) / m_pitchModel.range() ); } /*! \brief Returns current range for pitch bend in semitones */ int midiPitchRange() const { return m_pitchRangeModel.value(); } // play everything in given frame-range - creates note-play-handles virtual bool play( const MidiTime & _start, const fpp_t _frames, const f_cnt_t _frame_base, int _tco_num = -1 ); // create new view for me virtual TrackView * createView( TrackContainerView* tcv ); // create new track-content-object = pattern virtual TrackContentObject * createTCO( const MidiTime & _pos ); // called by track virtual void saveTrackSpecificSettings( QDomDocument & _doc, QDomElement & _parent ); virtual void loadTrackSpecificSettings( const QDomElement & _this ); using Track::setJournalling; // load instrument whose name matches given one Instrument * loadInstrument( const QString & _instrument_name ); AudioPort * audioPort() { return &m_audioPort; } MidiPort * midiPort() { return &m_midiPort; } const IntModel *baseNoteModel() const { return &m_baseNoteModel; } IntModel *baseNoteModel() { return &m_baseNoteModel; } int baseNote() const; Piano *pianoModel() { return &m_piano; } bool isArpeggioEnabled() const { return m_arpeggio.m_arpEnabledModel.value(); } // simple helper for removing midiport-XML-node when loading presets static void removeMidiPortNode( DataFile& dataFile ); FloatModel * pitchModel() { return &m_pitchModel; } FloatModel * volumeModel() { return &m_volumeModel; } FloatModel * panningModel() { return &m_panningModel; } IntModel* pitchRangeModel() { return &m_pitchRangeModel; } IntModel * effectChannelModel() { return &m_effectChannelModel; } void setIndicator( FadeButton *fb ); signals: void instrumentChanged(); void midiNoteOn( const Note& ); void midiNoteOff( const Note& ); void nameChanged(); protected: virtual QString nodeName() const { return "instrumenttrack"; } protected slots: void updateBaseNote(); void updatePitch(); void updatePitchRange(); private: MidiPort m_midiPort; NotePlayHandle* m_notes[NumKeys]; QMutex m_notesMutex; int m_runningMidiNotes[NumKeys]; QMutex m_midiNotesMutex; bool m_sustainPedalPressed; bool m_silentBuffersProcessed; IntModel m_baseNoteModel; NotePlayHandleList m_processHandles; FloatModel m_volumeModel; FloatModel m_panningModel; AudioPort m_audioPort; FloatModel m_pitchModel; IntModel m_pitchRangeModel; IntModel m_effectChannelModel; BoolModel m_useMasterPitchModel; FadeButton *m_fb; Instrument * m_instrument; InstrumentSoundShaping m_soundShaping; InstrumentFunctionArpeggio m_arpeggio; InstrumentFunctionNoteStacking m_noteStacking; Piano m_piano; friend class InstrumentTrackView; friend class InstrumentTrackWindow; friend class NotePlayHandle; friend class FlpImport; friend class InstrumentMiscView; } ; class InstrumentTrackView : public TrackView { Q_OBJECT public: InstrumentTrackView( InstrumentTrack * _it, TrackContainerView* tc ); virtual ~InstrumentTrackView(); InstrumentTrackWindow * getInstrumentTrackWindow(); InstrumentTrack * model() { return castModel(); } const InstrumentTrack * model() const { return castModel(); } static InstrumentTrackWindow * topLevelInstrumentTrackWindow(); QMenu * midiMenu() { return m_midiMenu; } void freeInstrumentTrackWindow(); static void cleanupWindowCache(); // Create a menu for assigning/creating channels for this track QMenu * createFxMenu( QString title, QString newFxLabel ); protected: virtual void dragEnterEvent( QDragEnterEvent * _dee ); virtual void dropEvent( QDropEvent * _de ); private slots: void toggleInstrumentWindow( bool _on ); void activityIndicatorPressed(); void activityIndicatorReleased(); void midiInSelected(); void midiOutSelected(); void midiConfigChanged(); void muteChanged(); void assignFxLine( int channelIndex ); void createFxLine(); private: InstrumentTrackWindow * m_window; static QQueue s_windowCache; // widgets in track-settings-widget TrackLabelButton * m_tlb; Knob * m_volumeKnob; Knob * m_panningKnob; FadeButton * m_activityIndicator; QMenu * m_midiMenu; QAction * m_midiInputAction; QAction * m_midiOutputAction; QPoint m_lastPos; friend class InstrumentTrackWindow; } ; class InstrumentTrackWindow : public QWidget, public ModelView, public SerializingObjectHook { Q_OBJECT public: InstrumentTrackWindow( InstrumentTrackView * _tv ); virtual ~InstrumentTrackWindow(); // parent for all internal tab-widgets TabWidget * tabWidgetParent() { return m_tabWidget; } InstrumentTrack * model() { return castModel(); } const InstrumentTrack * model() const { return castModel(); } void setInstrumentTrackView( InstrumentTrackView * _tv ); InstrumentTrackView *instrumentTrackView() { return m_itv; } PianoView * pianoView() { return m_pianoView; } static void dragEnterEventGeneric( QDragEnterEvent * _dee ); virtual void dragEnterEvent( QDragEnterEvent * _dee ); virtual void dropEvent( QDropEvent * _de ); public slots: void textChanged( const QString & _new_name ); void toggleVisibility( bool _on ); void updateName(); void updateInstrumentView(); protected: // capture close-events for toggling instrument-track-button virtual void closeEvent( QCloseEvent * _ce ); virtual void focusInEvent( QFocusEvent * _fe ); virtual void saveSettings( QDomDocument & _doc, QDomElement & _this ); virtual void loadSettings( const QDomElement & _this ); protected slots: void saveSettingsBtnClicked(); void viewNextInstrument(); void viewPrevInstrument(); private: virtual void modelChanged(); void viewInstrumentInDirection(int d); InstrumentTrack * m_track; InstrumentTrackView * m_itv; // widgets on the top of an instrument-track-window QLineEdit * m_nameLineEdit; LeftRightNav * m_leftRightNav; Knob * m_volumeKnob; Knob * m_panningKnob; Knob * m_pitchKnob; LcdSpinBox* m_pitchRangeSpinBox; LcdSpinBox * m_effectChannelNumber; // tab-widget with all children TabWidget * m_tabWidget; PluginView * m_instrumentView; InstrumentSoundShapingView * m_ssView; InstrumentFunctionNoteStackingView* m_noteStackingView; InstrumentFunctionArpeggioView* m_arpeggioView; InstrumentMidiIOView * m_midiView; EffectRackView * m_effectView; InstrumentMiscView *m_miscView; // test-piano at the bottom of every instrument-settings-window PianoView * m_pianoView; friend class InstrumentView; } ; #endif