diff --git a/ChangeLog b/ChangeLog index 30abe3c85..75e0582f3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,32 @@ +2008-06-07 Tobias Doerffel + + * include/controller_connection_dialog.h: + * include/instrument_midi_io_view.h: + * include/instrument_track.h: + * include/midi_alsa_raw.h: + * include/midi_alsa_seq.h: + * include/midi_client.h: + * include/midi_controller.h: + * include/midi_io_model.h: + * include/midi_oss.h: + * include/midi_port.h: + * include/midi_port_menu.h: + * src/core/note_play_handle.cpp: + * src/core/preset_preview_play_handle.cpp: + * src/core/song.cpp: + * src/core/midi/midi_client.cpp: + * src/core/midi/midi_controller.cpp: + * src/core/midi/midi_port.cpp: + * src/core/midi/midi_io_model.cpp: + * src/core/midi/midi_alsa_seq.cpp: + * src/gui/piano_roll.cpp: + * src/gui/controller_connection_dialog.cpp: + * src/gui/widgets/instrument_midi_io_view.cpp: + * src/tracks/instrument_track.cpp: + * Makefile.am: + rewrote management of MIDI-ports and MIDI-port subscriptions - now + it's central and easy to use + 2008-06-06 Tobias Doerffel * include/note.h: diff --git a/Makefile.am b/Makefile.am index e6ddf9c8b..e086ddd6d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -113,8 +113,6 @@ lmms_MOC = \ ./group_box.moc \ ./instrument_functions.moc \ ./instrument_function_views.moc \ - ./instrument_midi_io.moc \ - ./instrument_midi_io_view.moc \ ./instrument_sound_shaping.moc \ ./instrument_sound_shaping_view.moc \ ./kmultitabbar.moc \ @@ -125,14 +123,15 @@ lmms_MOC = \ ./led_checkbox.moc \ ./lfo_controller.moc \ ./main_window.moc \ + ./meter_model.moc \ + ./midi_alsa_seq.moc \ + ./midi_controller.moc \ + ./midi_port.moc \ + ./midi_port_menu.moc \ ./mixer.moc \ ./mv_base.moc \ ./name_label.moc \ ./nstate_button.moc \ - ./meter_model.moc \ - ./midi_alsa_seq.moc \ - ./midi_controller.moc \ - ./instrument_midi_io.moc \ ./pattern.moc \ ./piano_roll.moc \ ./piano.moc \ @@ -218,7 +217,6 @@ lmms_SOURCES = \ $(srcdir)/src/core/import_filter.cpp \ $(srcdir)/src/core/instrument.cpp \ $(srcdir)/src/core/instrument_functions.cpp \ - $(srcdir)/src/core/instrument_midi_io.cpp \ $(srcdir)/src/core/journalling_object.cpp \ $(srcdir)/src/core/ladspa_2_lmms.cpp \ $(srcdir)/src/core/ladspa_manager.cpp \ @@ -261,7 +259,7 @@ lmms_SOURCES = \ $(srcdir)/src/core/midi/midi_alsa_raw.cpp \ $(srcdir)/src/core/midi/midi_alsa_seq.cpp \ $(srcdir)/src/core/midi/midi_client.cpp \ - $(srcdir)/src/core/midi/midi_controller.cpp \ + $(srcdir)/src/core/midi/midi_controller.cpp \ $(srcdir)/src/core/midi/midi_mapper.cpp \ $(srcdir)/src/core/midi/midi_oss.cpp \ $(srcdir)/src/core/midi/midi_port.cpp \ @@ -310,6 +308,7 @@ lmms_SOURCES = \ $(srcdir)/src/gui/widgets/lcd_spinbox.cpp \ $(srcdir)/src/gui/widgets/led_checkbox.cpp \ $(srcdir)/src/gui/widgets/meter_dialog.cpp \ + $(srcdir)/src/gui/widgets/midi_port_menu.cpp \ $(srcdir)/src/gui/widgets/name_label.cpp \ $(srcdir)/src/gui/widgets/nstate_button.cpp \ $(srcdir)/src/gui/widgets/pixmap_button.cpp \ @@ -414,10 +413,11 @@ lmms_SOURCES = \ $(srcdir)/include/midi.h \ $(srcdir)/include/midi_alsa_raw.h \ $(srcdir)/include/midi_client.h \ - $(srcdir)/include/midi_controller.h \ + $(srcdir)/include/midi_controller.h \ $(srcdir)/include/midi_event_processor.h \ $(srcdir)/include/midi_oss.h \ $(srcdir)/include/midi_port.h \ + $(srcdir)/include/midi_port_menu.h \ $(srcdir)/include/midi_time.h \ $(srcdir)/include/clipboard.h \ $(srcdir)/include/types.h \ @@ -449,7 +449,6 @@ lmms_SOURCES = \ $(srcdir)/include/dummy_instrument.h \ $(srcdir)/include/instrument_play_handle.h \ $(srcdir)/include/string_pair_drag.h \ - $(srcdir)/include/instrument_midi_io.h \ $(srcdir)/include/instrument_midi_io_view.h \ $(srcdir)/include/audio_port.h \ $(srcdir)/include/tool.h \ @@ -491,7 +490,7 @@ lmms_SOURCES = \ $(srcdir)/include/ladspa_control_view.h \ $(srcdir)/include/ladspa_base.h \ $(srcdir)/include/controller.h \ - $(srcdir)/include/controller_connection.h \ + $(srcdir)/include/controller_connection.h \ $(srcdir)/include/controller_rack_view.h \ $(srcdir)/include/controller_view.h \ $(srcdir)/include/controller_dialog.h \ diff --git a/include/controller_connection_dialog.h b/include/controller_connection_dialog.h index d032177bc..af2cce14b 100644 --- a/include/controller_connection_dialog.h +++ b/include/controller_connection_dialog.h @@ -38,11 +38,12 @@ class QLineEdit; class QListView; class QScrollArea; +class autoDetectMidiController; +class comboBox; class groupBox; class lcdSpinBox; class ledCheckBox; -class comboBox; -class autoDetectMidiController; +class midiPortMenu; @@ -69,16 +70,13 @@ public slots: protected slots: void midiValueChanged( void ); - void activatedReadablePort( QAction * _item ); - void updateReadablePortsMenu( void ); private: - groupBox * m_midiGroupBox; lcdSpinBox * m_midiChannelSpinBox; lcdSpinBox * m_midiControllerSpinBox; ledCheckBox * m_midiAutoDetectCheckBox; - QMenu * m_readablePorts; + midiPortMenu * m_readablePorts; boolModel m_midiAutoDetect; groupBox * m_userGroupBox; diff --git a/include/instrument_midi_io_view.h b/include/instrument_midi_io_view.h index 1ef06e8be..4134c0cdb 100644 --- a/include/instrument_midi_io_view.h +++ b/include/instrument_midi_io_view.h @@ -32,30 +32,21 @@ #include "mv_base.h" -class QMenu; -class QAction; - class tabWidget; class ledCheckBox; class lcdSpinBox; +class midiPortMenu; class instrumentMidiIOView : public QWidget, public modelView { - Q_OBJECT public: - instrumentMidiIOView( QWidget * _parent ); + instrumentMidiIOView( midiPortMenu * _readable_ports_menu, + midiPortMenu * _writable_ports_menu, + QWidget * _parent ); virtual ~instrumentMidiIOView(); -protected slots: - void activatedReadablePort( QAction * _item ); - void activatedWriteablePort( QAction * _item ); - - void updateReadablePortsMenu( void ); - void updateWriteablePortsMenu( void ); - - private: virtual void modelChanged( void ); @@ -67,12 +58,6 @@ private: ledCheckBox * m_defaultVelocityInCheckBox; ledCheckBox * m_defaultVelocityOutCheckBox; - QMenu * m_readablePorts; - QMenu * m_writeablePorts; - - - friend class instrumentTrackWindow; - } ; diff --git a/include/instrument_track.h b/include/instrument_track.h index 391804477..79d5c73a6 100644 --- a/include/instrument_track.h +++ b/include/instrument_track.h @@ -32,10 +32,10 @@ #include "audio_port.h" #include "automatable_model.h" #include "instrument_functions.h" -#include "instrument_midi_io.h" #include "instrument_sound_shaping.h" #include "lcd_spinbox.h" #include "midi_event_processor.h" +#include "midi_port.h" #include "mixer.h" #include "piano.h" #include "effect_chain.h" @@ -51,10 +51,10 @@ class effectRackView; class instrumentSoundShapingView; class fadeButton; class instrument; -class instrumentMidiIOView; class instrumentTrackButton; class instrumentTrackWindow; -class midiPort; +class instrumentMidiIOView; +class midiPortMenu; class notePlayHandle; class pluginView; class presetPreviewPlayHandle; @@ -167,8 +167,8 @@ protected slots: private: - midiPort * m_midiPort; audioPort m_audioPort; + midiPort m_midiPort; notePlayHandle * m_notes[NumKeys]; @@ -186,7 +186,6 @@ private: instrumentSoundShaping m_soundShaping; arpeggiator m_arpeggiator; chordCreator m_chordCreator; - instrumentMidiIO m_midiIO; piano m_piano; @@ -234,6 +233,10 @@ private slots: void updateName( void ); + void midiInSelected( void ); + void midiOutSelected( void ); + void midiConfigChanged( void ); + private: instrumentTrackWindow * m_window; @@ -246,6 +249,11 @@ private: instrumentTrackButton * m_tswInstrumentTrackButton; QMenu * m_tswMidiMenu; + midiPortMenu * m_readablePortsMenu; + midiPortMenu * m_writablePortsMenu; + + QAction * m_midiInputAction; + QAction * m_midiOutputAction; friend class instrumentTrackButton; @@ -292,10 +300,6 @@ public slots: void updateName( void ); void updateInstrumentView( void ); - void midiInSelected( void ); - void midiOutSelected( void ); - void midiConfigChanged( bool ); - protected: // capture close-events for toggling instrument-track-button @@ -339,9 +343,6 @@ private: // test-piano at the bottom of every instrument-settings-window pianoView * m_pianoView; - QAction * m_midiInputAction; - QAction * m_midiOutputAction; - friend class instrumentTrackButton; friend class instrumentView; diff --git a/include/midi_alsa_raw.h b/include/midi_alsa_raw.h index 33b168cc8..351682be1 100644 --- a/include/midi_alsa_raw.h +++ b/include/midi_alsa_raw.h @@ -78,7 +78,7 @@ public: protected: - virtual void FASTCALL sendByte( const Uint8 _c ); + virtual void sendByte( const Uint8 _c ); virtual void run( void ); diff --git a/include/midi_alsa_seq.h b/include/midi_alsa_seq.h index a2cc5c7bd..6fb4f4c78 100644 --- a/include/midi_alsa_seq.h +++ b/include/midi_alsa_seq.h @@ -70,14 +70,14 @@ public: - virtual void FASTCALL processOutEvent( const midiEvent & _me, + virtual void processOutEvent( const midiEvent & _me, const midiTime & _time, const midiPort * _port ); - virtual void FASTCALL applyPortMode( midiPort * _port ); - virtual void FASTCALL applyPortName( midiPort * _port ); + virtual void applyPortMode( midiPort * _port ); + virtual void applyPortName( midiPort * _port ); - virtual void FASTCALL removePort( midiPort * _port ); + virtual void removePort( midiPort * _port ); // list seq-ports from ALSA @@ -94,10 +94,10 @@ public: // (un)subscribe given midiPort to/from destination-port virtual void subscribeReadablePort( midiPort * _port, const QString & _dest, - bool _unsubscribe = FALSE ); + bool _subscribe = TRUE ); virtual void subscribeWriteablePort( midiPort * _port, const QString & _dest, - bool _unsubscribe = FALSE ); + bool _subscribe = TRUE ); virtual void connectRPChanged( QObject * _receiver, const char * _member ) { diff --git a/include/midi_client.h b/include/midi_client.h index b51aa74f3..149cc7be5 100644 --- a/include/midi_client.h +++ b/include/midi_client.h @@ -1,7 +1,7 @@ /* * midi_client.h - base-class for MIDI-clients like ALSA-sequencer-client * - * Copyright (c) 2005-2007 Tobias Doerffel + * Copyright (c) 2005-2008 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -46,24 +46,19 @@ public: virtual ~midiClient(); // to be implemented by sub-classes - virtual void FASTCALL processOutEvent( const midiEvent & _me, + virtual void processOutEvent( const midiEvent & _me, const midiTime & _time, const midiPort * _port ) = 0; // inheriting classes can re-implement this for being able to update // their internal port-structures etc. - virtual void FASTCALL applyPortMode( midiPort * _port ); - virtual void FASTCALL applyPortName( midiPort * _port ); + virtual void applyPortMode( midiPort * _port ); + virtual void applyPortName( midiPort * _port ); - // inheriting classes can re-implement this although it's actually not - // neccessary, because they can catch port-mode-changes and do their - // stuff as soon as port-mode changes from DUMMY to something else - // re-implemented methods HAVE to call addPort() of base-class!! - virtual midiPort * FASTCALL addPort( midiEventProcessor * _mep, - const QString & _name ); + virtual void addPort( midiPort * _port ); // re-implemented methods HAVE to call removePort() of base-class!! - virtual void FASTCALL removePort( midiPort * _port ); + virtual void removePort( midiPort * _port ); // returns whether client works with raw-MIDI, only needs to be @@ -80,10 +75,10 @@ public: // (un)subscribe given midiPort to/from destination-port virtual void subscribeReadablePort( midiPort * _port, const QString & _dest, - bool _unsubscribe = FALSE ); + bool _subscribe = TRUE ); virtual void subscribeWriteablePort( midiPort * _port, const QString & _dest, - bool _unsubscribe = FALSE ); + bool _subscribe = TRUE ); // qobject-derived classes can use this for make a slot being // connected to signal of non-raw-MIDI-client if port-lists change @@ -152,22 +147,22 @@ public: protected: // generic raw-MIDI-parser which generates appropriate MIDI-events - void FASTCALL parseData( const Uint8 _c ); + void parseData( const Uint8 _c ); // to be implemented by actual client-implementation - virtual void FASTCALL sendByte( const Uint8 _c ) = 0; + virtual void sendByte( const Uint8 _c ) = 0; private: // this does MIDI-event-process void processParsedEvent(); - virtual void FASTCALL processOutEvent( const midiEvent & _me, + virtual void processOutEvent( const midiEvent & _me, const midiTime & _time, const midiPort * _port ); // small helper function returning length of a certain event - this // is neccessary for parsing raw-MIDI-data - static Uint8 FASTCALL eventLength( const Uint8 _event ); + static Uint8 eventLength( const Uint8 _event ); // data being used for parsing diff --git a/include/midi_controller.h b/include/midi_controller.h index 855077dc2..3da728fc9 100644 --- a/include/midi_controller.h +++ b/include/midi_controller.h @@ -26,13 +26,11 @@ #define _MIDI_CONTROLLER_H #include -#include -#include "mv_base.h" #include "automatable_model.h" #include "controller.h" -#include "controller_dialog.h" #include "midi_event_processor.h" +#include "midi_port.h" class midiPort; @@ -42,18 +40,16 @@ class midiController : public controller, public midiEventProcessor { Q_OBJECT public: - typedef QMap midiPortMap; - midiController( model * _parent ); virtual ~midiController(); + #warning TODO: use displayName-property! virtual QString publicName() const { return "MIDI Controller"; } - virtual void processInEvent( const midiEvent & _me, const midiTime & _time, bool _lock = TRUE ); @@ -68,45 +64,29 @@ public: virtual void loadSettings( const QDomElement & _this ); virtual QString nodeName( void ) const; - virtual intModel * midiChannelModel( void ) - { - return &m_midiChannel; - } - - - virtual intModel * midiControllerModel( void ) - { - return &m_midiController; - } - - virtual midiPort * getMidiPort( void ) - { - return m_midiPort; - } - // Used by controllerConnectionDialog to copy - virtual void setReadablePorts( const midiPortMap & _map ); + void subscribeReadablePorts( const midiPort::map & _map ); + public slots: virtual controllerDialog * createDialog( QWidget * _parent ); - void updateMidiPort( void ); - void updateReadablePorts( void ); + void updateName( void ); + protected: - // The internal per-controller get-value function virtual float value( int _offset ); - intModel m_midiChannel; - intModel m_midiController; - midiPort * m_midiPort; - midiPortMap m_readablePorts; + midiPort m_midiPort; + float m_lastValue; friend class controllerConnectionDialog; -}; + friend class autoDetectMidiController; + +} ; #endif diff --git a/include/midi_io_model.h b/include/midi_io_model.h deleted file mode 100644 index b99045ede..000000000 --- a/include/midi_io_model.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * instrument_midi_io.h - class instrumentMidiIO - * - * Copyright (c) 2005-2008 Tobias Doerffel - * - * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net - * - * 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_MIDI_IO_H -#define _INSTRUMENT_MIDI_IO_H - -#include -#include - -#include "automatable_model.h" - - -class instrumentTrack; -class midiPort; - - -class instrumentMidiIO : public model, public journallingObject -{ - Q_OBJECT -public: - typedef QPair descriptiveMidiPort; - typedef QList midiPortMap; - - instrumentMidiIO( instrumentTrack * _instrument_track, - midiPort * _port ); - virtual ~instrumentMidiIO(); - - - virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent ); - virtual void loadSettings( const QDomElement & _this ); - virtual QString nodeName( void ) const - { - return( "midi" ); - } - - -signals: - void readablePortsChanged( void ); - void writeablePortsChanged( void ); - - -public slots: - void updateMidiPortMode( void ); - - -protected slots: - void updateInputChannel( void ); - void updateOutputChannel( void ); - void updateDefaultVelIn( void ); - void updateDefaultVelOut( void ); - void updateReadablePorts( void ); - void updateWriteablePorts( void ); - - void activatedReadablePort( const descriptiveMidiPort & _port ); - void activatedWriteablePort( const descriptiveMidiPort & _port ); - - -private: - instrumentTrack * m_instrumentTrack; - midiPort * m_midiPort; - - intModel m_inputChannelModel; - intModel m_outputChannelModel; - boolModel m_receiveEnabledModel; - boolModel m_sendEnabledModel; - boolModel m_defaultVelocityInEnabledModel; - boolModel m_defaultVelocityOutEnabledModel; - - midiPortMap m_readablePorts; - midiPortMap m_writeablePorts; - - - friend class instrumentMidiIOView; - -} ; - - -#endif diff --git a/include/midi_oss.h b/include/midi_oss.h index d7a3fa06f..7ec2d096f 100644 --- a/include/midi_oss.h +++ b/include/midi_oss.h @@ -71,7 +71,7 @@ public: protected: - virtual void FASTCALL sendByte( const Uint8 _c ); + virtual void sendByte( const Uint8 _c ); virtual void run( void ); diff --git a/include/midi_port.h b/include/midi_port.h index eab1aa571..b54d2e36e 100644 --- a/include/midi_port.h +++ b/include/midi_port.h @@ -2,7 +2,7 @@ * midi_port.h - abstraction of MIDI-ports which are part of LMMS's MIDI- * sequencing system * - * Copyright (c) 2005-2007 Tobias Doerffel + * Copyright (c) 2005-2008 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -28,14 +28,11 @@ #define _MIDI_PORT_H #include +#include +#include -#ifdef HAVE_CONFIG_H -#include -#endif - - -#include "types.h" #include "midi.h" +#include "automatable_model.h" class midiClient; @@ -44,9 +41,22 @@ class midiTime; // class for abstraction of MIDI-port -class midiPort +class midiPort : public model, public serializingObject { + Q_OBJECT + mapPropertyFromModel(int,inputChannel,setInputChannel, + m_inputChannelModel); + mapPropertyFromModel(int,outputChannel,setOutputChannel, + m_outputChannelModel); + mapPropertyFromModel(int,inputController,setInputController, + m_inputControllerModel); + mapPropertyFromModel(int,outputController,setOutputController, + m_outputControllerModel); + mapPropertyFromModel(bool,isReadable,setReadable,m_readableModel); + mapPropertyFromModel(bool,isWritable,setWritable,m_writableModel); public: + typedef QMap map; + enum Modes { Disabled, // don't route any MIDI-events (default) @@ -55,71 +65,105 @@ public: Duplex // both directions } ; - midiPort( midiClient * _mc, midiEventProcessor * _mep, - const QString & _name, Modes _mode = Disabled ); - ~midiPort(); + midiPort( const QString & _name, + midiClient * _mc, + midiEventProcessor * _mep, + model * _parent = NULL, + track * _track = NULL, + Modes _mode = Disabled ); + virtual ~midiPort(); inline const QString & name( void ) const { return( m_name ); } - void FASTCALL setName( const QString & _name ); + void setName( const QString & _name ); inline Modes mode( void ) const { return( m_mode ); } - void FASTCALL setMode( Modes _mode ); - - inline Sint8 inputChannel( void ) const - { - return( m_inputChannel ); - } - - inline void setInputChannel( Sint8 _chnl ) - { - m_inputChannel = _chnl; - } + void setMode( Modes _mode ); inline void enableDefaultVelocityForInEvents( const bool _on ) { - m_defaultVelocityForInEventsEnabled = _on; - } - - inline Sint8 outputChannel( void ) const - { - return( m_outputChannel ); - } - - inline void setOutputChannel( Sint8 _chnl ) - { - m_outputChannel = _chnl; + m_defaultVelocityInEnabledModel.setValue( _on ); } inline void enableDefaultVelocityForOutEvents( const bool _on ) { - m_defaultVelocityForOutEventsEnabled = _on; + m_defaultVelocityOutEnabledModel.setValue( _on ); } + void processInEvent( const midiEvent & _me, const midiTime & _time ); + void processOutEvent( const midiEvent & _me, const midiTime & _time ); - void FASTCALL processInEvent( const midiEvent & _me, - const midiTime & _time ); - void FASTCALL processOutEvent( const midiEvent & _me, - const midiTime & _time ); + + virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent ); + virtual void loadSettings( const QDomElement & _this ); + + virtual QString nodeName( void ) const + { + return( "midiport" ); + } + + void subscribeReadablePort( const QString & _port, + bool _subscribe = TRUE ); + void subscribeWriteablePort( const QString & _port, + bool _subscribe = TRUE ); + + const map & readablePorts( void ) const + { + return( m_readablePorts ); + } + + const map & writablePorts( void ) const + { + return( m_writablePorts ); + } + + +signals: + void readablePortsChanged( void ); + void writeablePortsChanged( void ); + void modeChanged( void ); + + +public slots: + void updateMidiPortMode( void ); + + +private slots: + void updateReadablePorts( void ); + void updateWriteablePorts( void ); private: midiClient * m_midiClient; midiEventProcessor * m_midiEventProcessor; - QString m_name; + + QString m_name; // TODO: replace with model-name-property! + Modes m_mode; - Sint8 m_inputChannel; - Sint8 m_outputChannel; - bool m_defaultVelocityForInEventsEnabled; - bool m_defaultVelocityForOutEventsEnabled; + + intModel m_inputChannelModel; + intModel m_outputChannelModel; + intModel m_inputControllerModel; + intModel m_outputControllerModel; + boolModel m_readableModel; + boolModel m_writableModel; + boolModel m_defaultVelocityInEnabledModel; + boolModel m_defaultVelocityOutEnabledModel; + + map m_readablePorts; + map m_writablePorts; + + + friend class controllerConnectionDialog; + friend class instrumentMidiIOView; } ; diff --git a/include/midi_port_menu.h b/include/midi_port_menu.h new file mode 100644 index 000000000..4e26eee78 --- /dev/null +++ b/include/midi_port_menu.h @@ -0,0 +1,60 @@ +/* + * midi_port_menu.h - a menu for subscribing a midiPort to several external + * MIDI ports + * + * Copyright (c) 2008 Tobias Doerffel + * + * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net + * + * 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 _MIDI_PORT_MENU_H +#define _MIDI_PORT_MENU_H + +#include + +#include "mv_base.h" +#include "midi_port.h" + + +class QAction; + + +class midiPortMenu : public QMenu, public modelView +{ + Q_OBJECT +public: + midiPortMenu( midiPort::Modes _mode ); + virtual ~midiPortMenu(); + + +protected slots: + void activatedPort( QAction * _item ); + void updatePorts( void ); + + +private: + virtual void modelChanged( void ); + + midiPort::Modes m_mode; + +} ; + + +#endif diff --git a/src/core/midi/midi_alsa_seq.cpp b/src/core/midi/midi_alsa_seq.cpp index 86622c8b5..72ef86975 100644 --- a/src/core/midi/midi_alsa_seq.cpp +++ b/src/core/midi/midi_alsa_seq.cpp @@ -323,7 +323,7 @@ void midiALSASeq::removePort( midiPort * _port ) void midiALSASeq::subscribeReadablePort( midiPort * _port, const QString & _dest, - bool _unsubscribe ) + bool _subscribe ) { if( m_portIDs.contains( _port ) == FALSE || ( _port->mode() != midiPort::Input && @@ -346,13 +346,13 @@ void midiALSASeq::subscribeReadablePort( midiPort * _port, snd_seq_port_subscribe_malloc( &subs ); snd_seq_port_subscribe_set_sender( subs, &sender ); snd_seq_port_subscribe_set_dest( subs, dest ); - if( _unsubscribe ) + if( _subscribe ) { - snd_seq_unsubscribe_port( m_seqHandle, subs ); + snd_seq_subscribe_port( m_seqHandle, subs ); } else { - snd_seq_subscribe_port( m_seqHandle, subs ); + snd_seq_unsubscribe_port( m_seqHandle, subs ); } snd_seq_port_subscribe_free( subs ); snd_seq_port_info_free( port_info ); @@ -363,7 +363,7 @@ void midiALSASeq::subscribeReadablePort( midiPort * _port, void midiALSASeq::subscribeWriteablePort( midiPort * _port, const QString & _dest, - bool _unsubscribe ) + bool _subscribe ) { if( m_portIDs.contains( _port ) == FALSE || ( _port->mode() != midiPort::Output && @@ -389,13 +389,13 @@ void midiALSASeq::subscribeWriteablePort( midiPort * _port, snd_seq_port_subscribe_malloc( &subs ); snd_seq_port_subscribe_set_sender( subs, sender ); snd_seq_port_subscribe_set_dest( subs, &dest ); - if( _unsubscribe ) + if( _subscribe ) { - snd_seq_unsubscribe_port( m_seqHandle, subs ); + snd_seq_subscribe_port( m_seqHandle, subs ); } else { - snd_seq_subscribe_port( m_seqHandle, subs ); + snd_seq_unsubscribe_port( m_seqHandle, subs ); } snd_seq_port_subscribe_free( subs ); snd_seq_port_info_free( port_info ); diff --git a/src/core/midi/midi_client.cpp b/src/core/midi/midi_client.cpp index f1d006567..399505d75 100644 --- a/src/core/midi/midi_client.cpp +++ b/src/core/midi/midi_client.cpp @@ -64,12 +64,9 @@ void midiClient::applyPortName( midiPort * ) -midiPort * midiClient::addPort( midiEventProcessor * _mep, - const QString & _name ) +void midiClient::addPort( midiPort * _port ) { - midiPort * port = new midiPort( this, _mep, _name ); - m_midiPorts.push_back( port ); - return( port ); + m_midiPorts.push_back( _port ); } @@ -82,7 +79,6 @@ void midiClient::removePort( midiPort * _port ) _port ); if( it != m_midiPorts.end() ) { - delete *it; m_midiPorts.erase( it ); } } diff --git a/src/core/midi/midi_controller.cpp b/src/core/midi/midi_controller.cpp index 06a600633..0f0eb58ec 100644 --- a/src/core/midi/midi_controller.cpp +++ b/src/core/midi/midi_controller.cpp @@ -34,7 +34,6 @@ #include "engine.h" #include "mixer.h" #include "midi_client.h" -#include "midi_port.h" #include "midi_controller.h" @@ -42,34 +41,19 @@ midiController::midiController( model * _parent ) : controller( MidiController, _parent ), midiEventProcessor(), - m_midiChannel( 0, 0, MIDI_CHANNEL_COUNT, this ), - m_midiController( 0, 0, MIDI_CONTROLLER_COUNT, this ), - m_midiPort( engine::getMixer()->getMIDIClient()->addPort( - this, tr( "unnamed_midi_controller" ) ) ), + m_midiPort( tr( "unnamed_midi_controller" ), + engine::getMixer()->getMIDIClient(), this, + this, NULL, midiPort::Input ), m_lastValue( 0.0f ) { - m_midiPort->setMode( midiPort::Input ); - - midiClient * mc = engine::getMixer()->getMIDIClient(); - if( mc->isRaw() == FALSE ) - { - updateReadablePorts(); - } - - connect( &m_midiChannel, SIGNAL( dataChanged() ), - this, SLOT( updateMidiPort() ) ); - connect( &m_midiController, SIGNAL( dataChanged() ), - this, SLOT( updateMidiPort() ) ); + connect( &m_midiPort, SIGNAL( modeChanged() ), + this, SLOT( updateName() ) ); } midiController::~midiController() { - m_midiChannel.disconnect( this ); - m_midiController.disconnect( this ); - - engine::getMixer()->getMIDIClient()->removePort( m_midiPort ); } @@ -83,12 +67,11 @@ float midiController::value( int _offset ) -void midiController::updateMidiPort( void ) +void midiController::updateName( void ) { - m_midiPort->setInputChannel( m_midiChannel.value() - 1 ); setName( QString("MIDI ch%1 ctrl%2"). - arg( m_midiChannel.value() ). - arg( m_midiController.value() ) ); + arg( m_midiPort.inputChannel() ). + arg( m_midiPort.inputController() ) ); } @@ -105,9 +88,9 @@ void midiController::processInEvent( const midiEvent & _me, bytes = _me.m_data.m_bytes; controllerNum = _me.m_data.m_bytes[0] & 0x7F; - if( m_midiController.value() == controllerNum + 1 && - ( m_midiChannel.value() == _me.m_channel + 1 || - m_midiChannel.value() == 0 ) ) + if( m_midiPort.inputController() == controllerNum + 1 && + ( m_midiPort.inputChannel() == _me.m_channel + 1 || + m_midiPort.inputChannel() == 0 ) ) { Uint8 val = _me.m_data.m_bytes[2] & 0x7F; m_lastValue = (float)( val ) / 127.0f; @@ -124,43 +107,13 @@ void midiController::processInEvent( const midiEvent & _me, -void midiController::setReadablePorts( const midiPortMap & _map ) +void midiController::subscribeReadablePorts( const midiPort::map & _map ) { - m_readablePorts.clear(); - - for( midiPortMap::const_iterator it = _map.constBegin(); - it != _map.constEnd(); ++it ) + for( midiPort::map::const_iterator it = _map.constBegin(); + it != _map.constEnd(); ++it ) { - engine::getMixer()->getMIDIClient()->subscribeReadablePort( - m_midiPort, it.key(), !( *it ) ); + m_midiPort.subscribeReadablePort( it.key(), *it ); } - - m_readablePorts = _map; -} - - -void midiController::updateReadablePorts( void ) -{ - // first save all selected ports - QStringList selected_ports; - - for( midiPortMap::const_iterator i = m_readablePorts.constBegin(); - i != m_readablePorts.constEnd(); ++i ) - { - selected_ports.push_back( i.key() ); - ++i; - } - - m_readablePorts.clear(); - const QStringList & wp = engine::getMixer()->getMIDIClient()-> - readablePorts(); - - // now insert new ports and restore selections - for( QStringList::const_iterator it = wp.begin(); it != wp.end(); ++it ) - { - m_readablePorts[ *it ] = ( selected_ports.indexOf( *it ) != -1 ); - } - //emit readablePortsChanged(); } @@ -169,28 +122,8 @@ void midiController::updateReadablePorts( void ) void midiController::saveSettings( QDomDocument & _doc, QDomElement & _this ) { controller::saveSettings( _doc, _this ); + m_midiPort.saveSettings( _doc, _this ); - m_midiChannel.saveSettings( _doc, _this, "channel" ); - m_midiController.saveSettings( _doc, _this, "controller" ); - - if( m_readablePorts.size() ) - { - QString rp; - for( midiPortMap::const_iterator it = m_readablePorts.constBegin(); - it != m_readablePorts.constEnd(); ++it ) - { - if( *it ) - { - rp += it.key() + ","; - } - } - // cut off comma - if( rp.length() > 0 ) - { - rp.truncate( rp.length() - 1 ); - } - _this.setAttribute( "inports", rp ); - } } @@ -200,28 +133,9 @@ void midiController::loadSettings( const QDomElement & _this ) { controller::loadSettings( _this ); - m_midiChannel.loadSettings( _this, "channel" ); - m_midiController.loadSettings( _this, "controller" ); + m_midiPort.loadSettings( _this ); - midiClient * mc = engine::getMixer()->getMIDIClient(); - if( mc->isRaw() == FALSE ) - { - //updateReadablePorts(); - - QStringList rp = _this.attribute( "inports" ).split( ',' ); - for( midiPortMap::iterator it = m_readablePorts.begin(); - it != m_readablePorts.end(); ++it ) - { - if( rp.indexOf( it.key() ) != -1 ) - { - *it = TRUE; - - engine::getMixer()->getMIDIClient()->subscribeReadablePort( - m_midiPort, it.key(), !( *it ) ); - } - } - } - updateMidiPort(); + updateName(); } diff --git a/src/core/midi/midi_io_model.cpp b/src/core/midi/midi_io_model.cpp deleted file mode 100644 index dd7ecb463..000000000 --- a/src/core/midi/midi_io_model.cpp +++ /dev/null @@ -1,374 +0,0 @@ -#ifndef SINGLE_SOURCE_COMPILE - -/* - * instrument_midi_io.cpp - class instrumentMidiIO - * - * Copyright (c) 2005-2008 Tobias Doerffel - * - * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net - * - * 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. - * - */ - - -#include - - -#include "instrument_midi_io.h" -#include "engine.h" -#include "instrument_track.h" -#include "midi_client.h" -#include "midi_port.h" -#include "song.h" - - - -instrumentMidiIO::instrumentMidiIO( instrumentTrack * _instrument_track, - midiPort * _port ) : - model( _instrument_track ), - m_instrumentTrack( _instrument_track ), - m_midiPort( _port ), - m_inputChannelModel( m_midiPort->inputChannel() + 1, - 0, MIDI_CHANNEL_COUNT, this ), - m_outputChannelModel( m_midiPort->outputChannel() + 1, - 1, MIDI_CHANNEL_COUNT, this ), - m_receiveEnabledModel( FALSE, this ), - m_sendEnabledModel( FALSE, this ), - m_defaultVelocityInEnabledModel( FALSE, this ), - m_defaultVelocityOutEnabledModel( FALSE, this ) -{ - m_inputChannelModel.setTrack( m_instrumentTrack ); - m_outputChannelModel.setTrack( m_instrumentTrack ); - m_receiveEnabledModel.setTrack( m_instrumentTrack ); - m_defaultVelocityInEnabledModel.setTrack( m_instrumentTrack ); - m_sendEnabledModel.setTrack( m_instrumentTrack ); - m_defaultVelocityOutEnabledModel.setTrack( m_instrumentTrack ); - - connect( &m_inputChannelModel, SIGNAL( dataChanged() ), - this, SLOT( updateInputChannel() ) ); - connect( &m_outputChannelModel, SIGNAL( dataChanged() ), - this, SLOT( updateOutputChannel() ) ); - connect( &m_receiveEnabledModel, SIGNAL( dataChanged() ), - this, SLOT( updateMidiPortMode() ) ); - connect( &m_defaultVelocityInEnabledModel, SIGNAL( dataChanged() ), - this, SLOT( updateDefaultVelIn() ) ); - connect( &m_sendEnabledModel, SIGNAL( dataChanged() ), - this, SLOT( updateMidiPortMode() ) ); - connect( &m_defaultVelocityOutEnabledModel, SIGNAL( dataChanged() ), - this, SLOT( updateDefaultVelOut() ) ); - - updateInputChannel(); - updateOutputChannel(); - - - const midiPort::Modes m = m_midiPort->mode(); - m_receiveEnabledModel.setValue( m == midiPort::Input || - m == midiPort::Duplex ); - m_sendEnabledModel.setValue( m == midiPort::Output || - m == midiPort::Duplex ); - - // when using with non-raw-clients we can provide buttons showing - // our port-menus when being clicked - midiClient * mc = engine::getMixer()->getMIDIClient(); - if( mc->isRaw() == FALSE ) - { - updateReadablePorts(); - updateWriteablePorts(); - - // we want to get informed about port-changes! - mc->connectRPChanged( this, SLOT( updateReadablePorts() ) ); - mc->connectWPChanged( this, SLOT( updateWriteablePorts() ) ); - } -} - - - - -instrumentMidiIO::~instrumentMidiIO() -{ -} - - - - -void instrumentMidiIO::saveSettings( QDomDocument & _doc, QDomElement & _this ) -{ - m_inputChannelModel.saveSettings( _doc, _this, "inputchannel" ); - m_outputChannelModel.saveSettings( _doc, _this, "outputchannel" ); - m_receiveEnabledModel.saveSettings( _doc, _this, "receive" ); - m_sendEnabledModel.saveSettings( _doc, _this, "send" ); - m_defaultVelocityInEnabledModel.saveSettings( _doc, _this, "defvelin" ); - m_defaultVelocityOutEnabledModel.saveSettings( _doc, _this, - "defvelout" ); - - if( m_receiveEnabledModel.value() == TRUE ) - { - QString rp; - for( midiPortMap::iterator it = m_readablePorts.begin(); - it != m_readablePorts.end(); ++it ) - { - if( it->second ) - { - rp += it->first + ","; - } - } - // cut off comma - if( rp.length() > 0 ) - { - rp.truncate( rp.length() - 1 ); - } - _this.setAttribute( "inports", rp ); - } - - if( m_sendEnabledModel.value() == TRUE ) - { - QString wp; - for( midiPortMap::iterator it = m_writeablePorts.begin(); - it != m_writeablePorts.end(); ++it ) - { - if( it->second ) - { - wp += it->first + ","; - } - } - // cut off comma - if( wp.length() > 0 ) - { - wp.truncate( wp.length() - 1 ); - } - _this.setAttribute( "outports", wp ); - } -} - - - - -void instrumentMidiIO::loadSettings( const QDomElement & _this ) -{ - m_inputChannelModel.loadSettings( _this, "inputchannel" ); - m_outputChannelModel.loadSettings( _this, "outputchannel" ); - m_receiveEnabledModel.loadSettings( _this, "receive" ); - m_sendEnabledModel.loadSettings( _this, "send" ); - m_defaultVelocityInEnabledModel.loadSettings( _this, "defvelin" ); - m_defaultVelocityOutEnabledModel.loadSettings( _this, "defvelout" ); - - // restore connections - - if( m_receiveEnabledModel.value() == TRUE ) - { - QStringList rp = _this.attribute( "inports" ).split( ',' ); - for( midiPortMap::iterator it = m_readablePorts.begin(); - it != m_readablePorts.end(); ++it ) - { - if( it->second != ( rp.indexOf( it->first ) != -1 ) ) - { - it->second = TRUE; - activatedReadablePort( *it ); - } - } - } - - if( m_sendEnabledModel.value() == TRUE ) - { - QStringList wp = _this.attribute( "outports" ).split( ',' ); - for( midiPortMap::iterator it = m_writeablePorts.begin(); - it != m_writeablePorts.end(); ++it ) - { - if( it->second != ( wp.indexOf( it->first ) != -1 ) ) - { - it->second = TRUE; - activatedWriteablePort( *it ); - } - } - } -} - - - - -void instrumentMidiIO::updateInputChannel( void ) -{ - m_midiPort->setInputChannel( m_inputChannelModel.value() - 1 ); - engine::getSong()->setModified(); -} - - - - -void instrumentMidiIO::updateOutputChannel( void ) -{ - m_midiPort->setOutputChannel( m_outputChannelModel.value() - 1 ); - engine::getSong()->setModified(); -} - - - - -void instrumentMidiIO::updateDefaultVelIn( void ) -{ - m_midiPort->enableDefaultVelocityForInEvents( - m_defaultVelocityInEnabledModel.value() ); -} - - - - -void instrumentMidiIO::updateDefaultVelOut( void ) -{ - m_midiPort->enableDefaultVelocityForOutEvents( - m_defaultVelocityOutEnabledModel.value() ); -} - - - - -void instrumentMidiIO::updateMidiPortMode( void ) -{ - // this small lookup-table makes everything easier - static const midiPort::Modes modeTable[2][2] = - { - { midiPort::Disabled, midiPort::Output }, - { midiPort::Input, midiPort::Duplex } - } ; - m_midiPort->setMode( modeTable[m_receiveEnabledModel.value()] - [m_sendEnabledModel.value()] ); - - // check whether we have to dis-check items in connection-menu - if( m_receiveEnabledModel.value() == FALSE ) - { - for( midiPortMap::iterator it = m_readablePorts.begin(); - it != m_readablePorts.end(); ++it ) - { - if( it->second == TRUE ) - { - it->second = FALSE; - activatedReadablePort( *it ); - } - } - } - - if( m_sendEnabledModel.value() == FALSE ) - { - for( midiPortMap::iterator it = m_writeablePorts.begin(); - it != m_writeablePorts.end(); ++it ) - { - if( it->second == TRUE ) - { - it->second = FALSE; - activatedWriteablePort( *it ); - } - } - } - engine::getSong()->setModified(); -} - - - - -void instrumentMidiIO::updateReadablePorts( void ) -{ - // first save all selected ports - QStringList selected_ports; - for( midiPortMap::iterator it = m_readablePorts.begin(); - it != m_readablePorts.end(); ++it ) - { - if( it->second == TRUE ) - { - selected_ports.push_back( it->first ); - } - } - - m_readablePorts.clear(); - const QStringList & wp = engine::getMixer()->getMIDIClient()-> - readablePorts(); - // now insert new ports and restore selections - for( QStringList::const_iterator it = wp.begin(); it != wp.end(); ++it ) - { - m_readablePorts.push_back( qMakePair( *it, - selected_ports.indexOf( *it ) != -1 ) ); - } - emit readablePortsChanged(); -} - - - - -void instrumentMidiIO::updateWriteablePorts( void ) -{ - // first save all selected ports - QStringList selected_ports; - for( midiPortMap::iterator it = m_writeablePorts.begin(); - it != m_writeablePorts.end(); ++it ) - { - if( it->second == TRUE ) - { - selected_ports.push_back( it->first ); - } - } - - m_writeablePorts.clear(); - const QStringList & wp = engine::getMixer()->getMIDIClient()-> - writeablePorts(); - // now insert new ports and restore selections - for( QStringList::const_iterator it = wp.begin(); it != wp.end(); ++it ) - { - m_writeablePorts.push_back( qMakePair( *it, - selected_ports.indexOf( *it ) != -1 ) ); - } - emit writeablePortsChanged(); -} - - - - -void instrumentMidiIO::activatedReadablePort( - const descriptiveMidiPort & _port ) -{ - // make sure, MIDI-port is configured for input - if( _port.second == TRUE && - m_midiPort->mode() != midiPort::Input && - m_midiPort->mode() != midiPort::Duplex ) - { - m_receiveEnabledModel.setValue( TRUE ); - } - engine::getMixer()->getMIDIClient()->subscribeReadablePort( m_midiPort, - _port.first, !_port.second ); -} - - - - -void instrumentMidiIO::activatedWriteablePort( - const descriptiveMidiPort & _port ) -{ - // make sure, MIDI-port is configured for output - if( _port.second == TRUE && - m_midiPort->mode() != midiPort::Output && - m_midiPort->mode() != midiPort::Duplex ) - { - m_sendEnabledModel.setValue( TRUE ); - } - engine::getMixer()->getMIDIClient()->subscribeWriteablePort( m_midiPort, - _port.first, !_port.second ); -} - - - -#include "instrument_midi_io.moc" - - -#endif diff --git a/src/core/midi/midi_port.cpp b/src/core/midi/midi_port.cpp index ff0079fff..f75ecd82f 100644 --- a/src/core/midi/midi_port.cpp +++ b/src/core/midi/midi_port.cpp @@ -26,23 +26,62 @@ */ +#include + #include "midi_port.h" #include "midi_client.h" -#include "volume.h" +#include "song.h" -midiPort::midiPort( midiClient * _mc, midiEventProcessor * _mep, - const QString & _name, Modes _mode ) : +midiPort::midiPort( const QString & _name, midiClient * _mc, + midiEventProcessor * _mep, model * _parent, + track * _track, Modes _mode ) : + model( _parent ), m_midiClient( _mc ), m_midiEventProcessor( _mep ), m_name( _name ), m_mode( _mode ), - m_inputChannel( -1 ), - m_outputChannel( -1 ), - m_defaultVelocityForInEventsEnabled( FALSE ), - m_defaultVelocityForOutEventsEnabled( FALSE ) + m_inputChannelModel( 0, 0, MIDI_CHANNEL_COUNT, this ), + m_outputChannelModel( 1, 1, MIDI_CHANNEL_COUNT, this ), + m_inputControllerModel( 0, 0, MIDI_CONTROLLER_COUNT, this ), + m_outputControllerModel( 0, 0, MIDI_CONTROLLER_COUNT, this ), + m_readableModel( FALSE, this ), + m_writableModel( FALSE, this ), + m_defaultVelocityInEnabledModel( FALSE, this ), + m_defaultVelocityOutEnabledModel( FALSE, this ) { + m_midiClient->addPort( this ); + + m_inputChannelModel.setTrack( _track ); + m_outputChannelModel.setTrack( _track ); + m_defaultVelocityInEnabledModel.setTrack( _track ); + m_defaultVelocityOutEnabledModel.setTrack( _track ); + + m_readableModel.setValue( m_mode == Input || m_mode == Duplex ); + m_writableModel.setValue( m_mode == Output || m_mode == Duplex ); + + connect( &m_readableModel, SIGNAL( dataChanged() ), + this, SLOT( updateMidiPortMode() ) ); + connect( &m_writableModel, SIGNAL( dataChanged() ), + this, SLOT( updateMidiPortMode() ) ); + + + // when using with non-raw-clients we can provide buttons showing + // our port-menus when being clicked + if( m_midiClient->isRaw() == FALSE ) + { + updateReadablePorts(); + updateWriteablePorts(); + + // we want to get informed about port-changes! + m_midiClient->connectRPChanged( this, + SLOT( updateReadablePorts() ) ); + m_midiClient->connectWPChanged( this, + SLOT( updateWriteablePorts() ) ); + } + + updateMidiPortMode(); } @@ -50,6 +89,7 @@ midiPort::midiPort( midiClient * _mc, midiEventProcessor * _mep, midiPort::~midiPort() { + m_midiClient->removePort( this ); } @@ -77,10 +117,10 @@ void midiPort::processInEvent( const midiEvent & _me, const midiTime & _time ) { // mask event if( ( mode() == Input || mode() == Duplex ) && - ( inputChannel() == _me.m_channel || inputChannel() == -1 ) ) + ( inputChannel()-1 == _me.m_channel || inputChannel() == 0 ) ) { midiEvent ev = _me; - if( m_defaultVelocityForInEventsEnabled == TRUE && + if( m_defaultVelocityInEnabledModel.value() == TRUE && _me.velocity() > 0 ) { ev.velocity() = DefaultVolume; @@ -96,10 +136,10 @@ void midiPort::processOutEvent( const midiEvent & _me, const midiTime & _time ) { // mask event if( ( mode() == Output || mode() == Duplex ) && - ( outputChannel() == _me.m_channel && outputChannel() != -1 ) ) + ( outputChannel()-1 == _me.m_channel && outputChannel() != 0 ) ) { midiEvent ev = _me; - if( m_defaultVelocityForOutEventsEnabled == TRUE && + if( m_defaultVelocityOutEnabledModel.value() == TRUE && _me.velocity() > 0 ) { ev.velocity() = DefaultVolume; @@ -110,4 +150,231 @@ void midiPort::processOutEvent( const midiEvent & _me, const midiTime & _time ) + +void midiPort::saveSettings( QDomDocument & _doc, QDomElement & _this ) +{ + m_inputChannelModel.saveSettings( _doc, _this, "inputchannel" ); + m_outputChannelModel.saveSettings( _doc, _this, "outputchannel" ); + m_inputControllerModel.saveSettings( _doc, _this, "inputcontroller" ); + m_outputControllerModel.saveSettings( _doc, _this, "outputcontroller" ); + m_readableModel.saveSettings( _doc, _this, "readable" ); + m_writableModel.saveSettings( _doc, _this, "writable" ); + m_defaultVelocityInEnabledModel.saveSettings( _doc, _this, "defvelin" ); + m_defaultVelocityOutEnabledModel.saveSettings( _doc, _this, + "defvelout" ); + + if( m_readableModel.value() == TRUE ) + { + QString rp; + for( midiPort::map::iterator it = m_readablePorts.begin(); + it != m_readablePorts.end(); ++it ) + { + if( it.value() ) + { + rp += it.key() + ","; + } + } + // cut off comma + if( rp.length() > 0 ) + { + rp.truncate( rp.length() - 1 ); + } + _this.setAttribute( "inports", rp ); + } + + if( m_writableModel.value() == TRUE ) + { + QString wp; + for( map::const_iterator it = m_writablePorts.begin(); + it != m_writablePorts.end(); ++it ) + { + if( it.value() ) + { + wp += it.key() + ","; + } + } + // cut off comma + if( wp.length() > 0 ) + { + wp.truncate( wp.length() - 1 ); + } + _this.setAttribute( "outports", wp ); + } +} + + + + +void midiPort::loadSettings( const QDomElement & _this ) +{ + m_inputChannelModel.loadSettings( _this, "inputchannel" ); + m_outputChannelModel.loadSettings( _this, "outputchannel" ); + m_inputControllerModel.loadSettings( _this, "inputcontroller" ); + m_outputControllerModel.loadSettings( _this, "outputcontroller" ); + m_readableModel.loadSettings( _this, "readable" ); + m_writableModel.loadSettings( _this, "writable" ); + m_defaultVelocityInEnabledModel.loadSettings( _this, "defvelin" ); + m_defaultVelocityOutEnabledModel.loadSettings( _this, "defvelout" ); + + // restore connections + + if( m_readableModel.value() == TRUE ) + { + QStringList rp = _this.attribute( "inports" ).split( ',' ); + for( map::const_iterator it = m_readablePorts.begin(); + it != m_readablePorts.end(); ++it ) + { + if( it.value() != ( rp.indexOf( it.key() ) != -1 ) ) + { + subscribeReadablePort( it.key() ); + } + } + } + + if( m_writableModel.value() == TRUE ) + { + QStringList wp = _this.attribute( "outports" ).split( ',' ); + for( map::const_iterator it = m_writablePorts.begin(); + it != m_writablePorts.end(); ++it ) + { + if( it.value() != ( wp.indexOf( it.key() ) != -1 ) ) + { + subscribeReadablePort( it.key() ); + } + } + } +} + + + + +void midiPort::updateMidiPortMode( void ) +{ + // this small lookup-table makes everything easier + static const Modes modeTable[2][2] = + { + { Disabled, Output }, + { Input, Duplex } + } ; + setMode( modeTable[m_readableModel.value()][m_writableModel.value()] ); + + // check whether we have to dis-check items in connection-menu + if( m_readableModel.value() == FALSE ) + { + for( map::const_iterator it = m_readablePorts.begin(); + it != m_readablePorts.end(); ++it ) + { + if( it.value() == TRUE ) + { + subscribeReadablePort( it.key(), FALSE ); + } + } + } + + if( m_writableModel.value() == FALSE ) + { + for( map::const_iterator it = m_writablePorts.begin(); + it != m_writablePorts.end(); ++it ) + { + if( it.value() == TRUE ) + { + subscribeWriteablePort( it.key(), FALSE ); + } + } + } + + emit readablePortsChanged(); + emit writeablePortsChanged(); + emit modeChanged(); + + engine::getSong()->setModified(); +} + + + + +void midiPort::updateReadablePorts( void ) +{ + // first save all selected ports + QStringList selected_ports; + for( midiPort::map::iterator it = m_readablePorts.begin(); + it != m_readablePorts.end(); ++it ) + { + if( it.value() == TRUE ) + { + selected_ports.push_back( it.key() ); + } + } + + m_readablePorts.clear(); + const QStringList & wp = engine::getMixer()->getMIDIClient()-> + readablePorts(); + // now insert new ports and restore selections + for( QStringList::const_iterator it = wp.begin(); it != wp.end(); ++it ) + { + m_readablePorts[*it] = ( selected_ports.indexOf( *it ) != -1 ); + } + emit readablePortsChanged(); +} + + + + +void midiPort::updateWriteablePorts( void ) +{ + // first save all selected ports + QStringList selected_ports; + for( midiPort::map::iterator it = m_writablePorts.begin(); + it != m_writablePorts.end(); ++it ) + { + if( it.value() == TRUE ) + { + selected_ports.push_back( it.key() ); + } + } + + m_writablePorts.clear(); + const QStringList & wp = engine::getMixer()->getMIDIClient()-> + writeablePorts(); + // now insert new ports and restore selections + for( QStringList::const_iterator it = wp.begin(); it != wp.end(); ++it ) + { + m_writablePorts[*it] = ( selected_ports.indexOf( *it ) != -1 ); + } + emit writeablePortsChanged(); +} + + + + +void midiPort::subscribeReadablePort( const QString & _port, bool _subscribe ) +{ + m_readablePorts[_port] = _subscribe; + // make sure, MIDI-port is configured for input + if( _subscribe == TRUE && mode() != Input && mode() != Duplex ) + { + m_readableModel.setValue( TRUE ); + } + m_midiClient->subscribeReadablePort( this, _port, _subscribe ); +} + + + + +void midiPort::subscribeWriteablePort( const QString & _port, bool _subscribe ) +{ + m_writablePorts[_port] = _subscribe; + // make sure, MIDI-port is configured for output + if( _subscribe == TRUE && mode() != Output && mode() != Duplex ) + { + m_writableModel.setValue( TRUE ); + } + m_midiClient->subscribeWriteablePort( this, _port, _subscribe ); +} + + + +#include "midi_port.moc" + + #endif diff --git a/src/core/note_play_handle.cpp b/src/core/note_play_handle.cpp index 5839773ce..d23dec639 100644 --- a/src/core/note_play_handle.cpp +++ b/src/core/note_play_handle.cpp @@ -105,7 +105,7 @@ notePlayHandle::notePlayHandle( instrumentTrack * _it, setFrames( _frames ); // send MIDI-note-on-event m_instrumentTrack->processOutEvent( midiEvent( NOTE_ON, - m_instrumentTrack->m_midiPort->outputChannel(), + m_instrumentTrack->m_midiPort.outputChannel(), key(), tLimit( (Uint16) ( ( getVolume() / 100.0f ) * @@ -303,7 +303,7 @@ void notePlayHandle::noteOff( const f_cnt_t _s ) m_instrumentTrack->m_soundShaping.releaseFrames() ); // send MIDI-note-off-event m_instrumentTrack->processOutEvent( midiEvent( NOTE_OFF, - m_instrumentTrack->m_midiPort->outputChannel(), + m_instrumentTrack->m_midiPort.outputChannel(), key(), 0 ), midiTime::fromFrames( m_framesBeforeRelease, engine::framesPerTick() ) ); diff --git a/src/core/preset_preview_play_handle.cpp b/src/core/preset_preview_play_handle.cpp index 89c902f5a..5f2ef1f9e 100644 --- a/src/core/preset_preview_play_handle.cpp +++ b/src/core/preset_preview_play_handle.cpp @@ -126,7 +126,7 @@ presetPreviewPlayHandle::presetPreviewPlayHandle( // make sure, our preset-preview-track does not appear in any MIDI- // devices list, so just disable receiving/sending MIDI-events at all - s_previewTC->previewInstrumentTrack()->m_midiPort->setMode( + s_previewTC->previewInstrumentTrack()->m_midiPort.setMode( midiPort::Disabled ); // create note-play-handle for it diff --git a/src/core/song.cpp b/src/core/song.cpp index 068a2b83a..4424103b9 100644 --- a/src/core/song.cpp +++ b/src/core/song.cpp @@ -117,6 +117,8 @@ song::song( void ) : /* connect( &m_masterPitchModel, SIGNAL( dataChanged() ), this, SLOT( masterPitchChanged() ) );*/ + qRegisterMetaType( "note" ); + } diff --git a/src/gui/controller_connection_dialog.cpp b/src/gui/controller_connection_dialog.cpp index 9d9144fdd..e60c37f82 100644 --- a/src/gui/controller_connection_dialog.cpp +++ b/src/gui/controller_connection_dialog.cpp @@ -39,7 +39,7 @@ #include "group_box.h" #include "midi_controller.h" #include "midi_client.h" -#include "midi_port.h" +#include "midi_port_menu.h" #include "midi.h" #include "song.h" #include "tool_button.h" @@ -55,7 +55,7 @@ public: m_detectedMidiChannel( 0 ), m_detectedMidiController( 0 ) { - updateMidiPort(); + updateName(); } @@ -68,8 +68,8 @@ public: const midiTime & _time, bool _lock ) { if( _me.m_type == CONTROL_CHANGE && - ( m_midiChannel.value() == _me.m_channel + 1 || - m_midiChannel.value() == 0 ) ) + ( m_midiPort.inputChannel() == _me.m_channel + 1 || + m_midiPort.inputChannel() == 0 ) ) { m_detectedMidiChannel = _me.m_channel + 1; m_detectedMidiController = ( _me.m_data.m_bytes[0] & 0x7F ) + 1; @@ -87,9 +87,9 @@ public: midiController * copyToMidiController( model * _parent ) { midiController * c = new midiController( _parent ); - c->midiChannelModel()->setValue( m_midiChannel.value() ); - c->midiControllerModel()->setValue( m_midiController.value() ); - c->setReadablePorts( m_readablePorts ); + c->m_midiPort.setInputChannel( m_midiPort.inputChannel() ); + c->m_midiPort.setInputController( m_midiPort.inputController() ); + c->subscribeReadablePorts( m_midiPort.readablePorts() ); return c; } @@ -97,16 +97,16 @@ public: void useDetected( void ) { - m_midiChannel.setValue( m_detectedMidiChannel ); - m_midiController.setValue( m_detectedMidiController ); + m_midiPort.setInputChannel( m_detectedMidiChannel ); + m_midiPort.setInputController( m_detectedMidiController ); } public slots: void reset( void ) { - m_midiChannel.setValue( 0 ); - m_midiController.setValue( 0 ); + m_midiPort.setInputChannel( 0 ); + m_midiPort.setInputController( 0 ); } }; @@ -162,14 +162,9 @@ controllerConnectionDialog::controllerConnectionDialog( QWidget * _parent, // when using with non-raw-clients we can provide buttons showing // our port-menus when being clicked - midiClient * mc = engine::getMixer()->getMIDIClient(); - if( mc->isRaw() == FALSE ) + if( !engine::getMixer()->getMIDIClient()->isRaw() ) { - m_readablePorts = new QMenu( this ); - m_readablePorts->setFont( pointSize<9>( - m_readablePorts->font() ) ); - connect( m_readablePorts, SIGNAL( triggered( QAction * ) ), - this, SLOT( activatedReadablePort( QAction * ) ) ); + m_readablePorts = new midiPortMenu( midiPort::Input ); toolButton * rp_btn = new toolButton( m_midiGroupBox ); rp_btn->setText( tr( "MIDI-devices to receive " @@ -251,13 +246,11 @@ controllerConnectionDialog::controllerConnectionDialog( QWidget * _parent, midiController * cont = (midiController*)( cc->getController() ); m_midiChannelSpinBox->model()->setValue( - cont->midiChannelModel()->value() ); + cont->m_midiPort.inputChannel() ); m_midiControllerSpinBox->model()->setValue( - cont->midiControllerModel()->value() ); + cont->m_midiPort.inputController() ); - // update menuupdateReadablePortsMenu - m_midiController->setReadablePorts( static_cast( cc->getController() )->m_readablePorts ); - updateReadablePortsMenu(); + m_midiController->subscribeReadablePorts( static_cast( cc->getController() )->m_midiPort.readablePorts() ); } else { @@ -307,13 +300,13 @@ void controllerConnectionDialog::selectController( void ) if( m_targetModel->getTrack() && !m_targetModel->getTrack()->displayName().isEmpty() ) { - mc->getMidiPort()->setName( QString( "%1 (%2)" ). + mc->m_midiPort.setName( QString( "%1 (%2)" ). arg( m_targetModel->getTrack()->displayName() ). arg( m_targetModel->displayName() ) ); } else { - mc->getMidiPort()->setName( m_targetModel->displayName() ); + mc->m_midiPort.setName( m_targetModel->displayName() ); } m_controller = mc; } @@ -348,15 +341,14 @@ void controllerConnectionDialog::midiToggled( void ) { m_midiController = new autoDetectMidiController( engine::getSong() ); m_midiChannelSpinBox->setModel( - m_midiController->midiChannelModel() ); + &m_midiController->m_midiPort.m_inputChannelModel ); m_midiControllerSpinBox->setModel( - m_midiController->midiControllerModel() ); + &m_midiController->m_midiPort.m_inputControllerModel ); + m_readablePorts->setModel( &m_midiController->m_midiPort ); connect( m_midiController, SIGNAL( valueChanged() ), this, SLOT( midiValueChanged() ) ); - - updateReadablePortsMenu(); } } else @@ -410,39 +402,6 @@ void controllerConnectionDialog::midiValueChanged( void ) -void controllerConnectionDialog::activatedReadablePort( QAction * _item ) -{ - // make sure, MIDI-port is configured for input - if( _item->isChecked() == TRUE && - m_midiController->m_midiPort->mode() != midiPort::Input && - m_midiController->m_midiPort->mode() != midiPort::Duplex ) - { - //mio->m_receiveEnabledModel.setValue( TRUE ); - } - engine::getMixer()->getMIDIClient()->subscribeReadablePort( - m_midiController->m_midiPort, _item->text(), !_item->isChecked() ); - m_midiController->m_readablePorts[_item->text()] = _item->isChecked(); -} - - - - -void controllerConnectionDialog::updateReadablePortsMenu( void ) -{ - if( m_readablePorts ) - { - m_readablePorts->clear(); - for( midiController::midiPortMap::const_iterator it = - m_midiController->m_readablePorts.begin(); - it != m_midiController->m_readablePorts.end(); ++it ) - { - QAction * a = m_readablePorts->addAction( it.key() ); - a->setCheckable( TRUE ); - a->setChecked( *it ); - } - } -} - #include "controller_connection_dialog.moc" #endif diff --git a/src/gui/piano_roll.cpp b/src/gui/piano_roll.cpp index 035539cc6..07e7821a0 100644 --- a/src/gui/piano_roll.cpp +++ b/src/gui/piano_roll.cpp @@ -515,7 +515,7 @@ void pianoRoll::setCurrentPattern( pattern * _new_pattern ) // of start-notes and so on...) resizeEvent( NULL ); - // remove all connections to other channel-tracks + // remove all connections to other instrument-tracks disconnect( this, SLOT( recordNote( const note & ) ) ); // and now connect to noteDone()-signal of channel so that diff --git a/src/gui/widgets/instrument_midi_io_view.cpp b/src/gui/widgets/instrument_midi_io_view.cpp index 7f5cd9ba6..74a1ec895 100644 --- a/src/gui/widgets/instrument_midi_io_view.cpp +++ b/src/gui/widgets/instrument_midi_io_view.cpp @@ -30,13 +30,9 @@ #include "instrument_midi_io_view.h" -#include "instrument_midi_io.h" +#include "midi_port_menu.h" #include "embed.h" -#include "engine.h" #include "gui_templates.h" -#include "midi_client.h" -#include "midi_port.h" -#include "mixer.h" #include "led_checkbox.h" #include "lcd_spinbox.h" #include "tab_widget.h" @@ -44,11 +40,12 @@ -instrumentMidiIOView::instrumentMidiIOView( QWidget * _parent ) : +instrumentMidiIOView::instrumentMidiIOView( + midiPortMenu * _readable_ports_menu, + midiPortMenu * _writable_ports_menu, + QWidget * _parent ) : QWidget( _parent ), - modelView( NULL ), - m_readablePorts( NULL ), - m_writeablePorts( NULL ) + modelView( NULL ) { m_setupTabWidget = new tabWidget( tr( "MIDI-SETUP FOR THIS CHANNEL" ), this ); @@ -101,38 +98,24 @@ instrumentMidiIOView::instrumentMidiIOView( QWidget * _parent ) : m_defaultVelocityOutCheckBox->move( 28, 164 ); - - // when using with non-raw-clients we can provide buttons showing - // our port-menus when being clicked - midiClient * mc = engine::getMixer()->getMIDIClient(); - if( mc->isRaw() == FALSE ) + if( _readable_ports_menu != NULL ) { - m_readablePorts = new QMenu( m_setupTabWidget ); - m_readablePorts->setFont( pointSize<9>( - m_readablePorts->font() ) ); - connect( m_readablePorts, SIGNAL( triggered( QAction * ) ), - this, SLOT( activatedReadablePort( QAction * ) ) ); - - m_writeablePorts = new QMenu( m_setupTabWidget ); - m_writeablePorts->setFont( pointSize<9>( - m_writeablePorts->font() ) ); - connect( m_writeablePorts, SIGNAL( triggered( QAction * ) ), - this, SLOT( activatedWriteablePort( QAction * ) ) ); - QToolButton * rp_btn = new QToolButton( m_setupTabWidget ); rp_btn->setText( tr( "MIDI-devices to receive " "MIDI-events from" ) ); rp_btn->setIcon( embed::getIconPixmap( "midi_in" ) ); rp_btn->setGeometry( 186, 34, 40, 40 ); - rp_btn->setMenu( m_readablePorts ); + rp_btn->setMenu( _readable_ports_menu ); rp_btn->setPopupMode( QToolButton::InstantPopup ); - + } + if( _writable_ports_menu != NULL ) + { QToolButton * wp_btn = new QToolButton( m_setupTabWidget ); wp_btn->setText( tr( "MIDI-devices to send MIDI-events " "to" ) ); wp_btn->setIcon( embed::getIconPixmap( "midi_out" ) ); wp_btn->setGeometry( 186, 114, 40, 40 ); - wp_btn->setMenu( m_writeablePorts ); + wp_btn->setMenu( _writable_ports_menu ); wp_btn->setPopupMode( QToolButton::InstantPopup ); } } @@ -149,101 +132,16 @@ instrumentMidiIOView::~instrumentMidiIOView() void instrumentMidiIOView::modelChanged( void ) { - instrumentMidiIO * mio = castModel(); - m_inputChannelSpinBox->setModel( &mio->m_inputChannelModel ); - m_outputChannelSpinBox->setModel( &mio->m_outputChannelModel ); - m_receiveCheckBox->setModel( &mio->m_receiveEnabledModel ); + midiPort * mp = castModel(); + m_inputChannelSpinBox->setModel( &mp->m_inputChannelModel ); + m_outputChannelSpinBox->setModel( &mp->m_outputChannelModel ); + m_receiveCheckBox->setModel( &mp->m_readableModel ); m_defaultVelocityInCheckBox->setModel( - &mio->m_defaultVelocityInEnabledModel ); - m_sendCheckBox->setModel( &mio->m_sendEnabledModel ); + &mp->m_defaultVelocityInEnabledModel ); + m_sendCheckBox->setModel( &mp->m_writableModel ); m_defaultVelocityOutCheckBox->setModel( - &mio->m_defaultVelocityOutEnabledModel ); - connect( mio, SIGNAL( readablePortsChanged() ), - this, SLOT( updateReadablePortsMenu() ) ); - connect( mio, SIGNAL( writeablePortsChanged() ), - this, SLOT( updateWriteablePortsMenu() ) ); - updateReadablePortsMenu(); - updateWriteablePortsMenu(); + &mp->m_defaultVelocityOutEnabledModel ); } - - -void instrumentMidiIOView::activatedReadablePort( QAction * _item ) -{ - instrumentMidiIO * mio = castModel(); - // make sure, MIDI-port is configured for input - if( _item->isChecked() == TRUE && - mio->m_midiPort->mode() != midiPort::Input && - mio->m_midiPort->mode() != midiPort::Duplex ) - { - mio->m_receiveEnabledModel.setValue( TRUE ); - } - engine::getMixer()->getMIDIClient()->subscribeReadablePort( - mio->m_midiPort, _item->text(), !_item->isChecked() ); -} - - - - -void instrumentMidiIOView::activatedWriteablePort( QAction * _item ) -{ - instrumentMidiIO * mio = castModel(); - // make sure, MIDI-port is configured for output - if( _item->isChecked() == TRUE && - mio->m_midiPort->mode() != midiPort::Output && - mio->m_midiPort->mode() != midiPort::Duplex ) - { - mio->m_sendEnabledModel.setValue( TRUE ); - } - engine::getMixer()->getMIDIClient()->subscribeWriteablePort( - mio->m_midiPort, _item->text(), !_item->isChecked() ); -} - - - - -void instrumentMidiIOView::updateReadablePortsMenu( void ) -{ - instrumentMidiIO * mio = castModel(); - if( m_readablePorts ) - { - m_readablePorts->clear(); - for( instrumentMidiIO::midiPortMap::const_iterator it = - mio->m_readablePorts.begin(); - it != mio->m_readablePorts.end(); ++it ) - { - QAction * a = m_readablePorts->addAction( it->first ); - a->setCheckable( TRUE ); - a->setChecked( it->second ); - } - } -} - - - - -void instrumentMidiIOView::updateWriteablePortsMenu( void ) -{ - instrumentMidiIO * mio = castModel(); - if( m_writeablePorts ) - { - m_writeablePorts->clear(); - for( instrumentMidiIO::midiPortMap::const_iterator it = - mio->m_writeablePorts.begin(); - it != mio->m_writeablePorts.end(); ++it ) - { - QAction * a = m_writeablePorts->addAction( it->first ); - a->setCheckable( TRUE ); - a->setChecked( it->second ); - } - } -} - - - - -#include "instrument_midi_io_view.moc" - - #endif diff --git a/src/tracks/instrument_track.cpp b/src/tracks/instrument_track.cpp index c9effab04..54addc98e 100644 --- a/src/tracks/instrument_track.cpp +++ b/src/tracks/instrument_track.cpp @@ -63,9 +63,8 @@ #include "led_checkbox.h" #include "main_window.h" #include "midi_client.h" -#include "midi_port.h" +#include "midi_port_menu.h" #include "fx_mixer.h" -#include "instrument_midi_io.h" #include "mmp.h" #include "note_play_handle.h" #include "pattern.h" @@ -104,19 +103,20 @@ const int INSTRUMENT_WINDOW_CACHE_SIZE = 8; instrumentTrack::instrumentTrack( trackContainer * _tc ) : track( InstrumentTrack, _tc ), midiEventProcessor(), - m_midiPort( engine::getMixer()->getMIDIClient()->addPort( this, - tr( "unnamed_channel" ) ) ), - m_audioPort( tr( "unnamed_channel" ), this ), + m_audioPort( tr( "unnamed_track" ), this ), + m_midiPort( tr( "unnamed_track" ), engine::getMixer()->getMIDIClient(), + this, this, this ), m_notes(), m_baseNoteModel( 0, 0, KeysPerOctave * NumOctaves - 1, this ), - m_volumeModel( DefaultVolume, MinVolume, MaxVolume, 1.0f, this, tr( "Volume" ) ), - m_panningModel( DefaultPanning, PanningLeft, PanningRight, 1.0f, this, tr( "Panning" ) ), + m_volumeModel( DefaultVolume, MinVolume, MaxVolume, 1.0f, this, + tr( "Volume" ) ), + m_panningModel( DefaultPanning, PanningLeft, PanningRight, 1.0f, + this, tr( "Panning" ) ), m_effectChannelModel( 0, 0, NumFxChannels, this ), m_instrument( NULL ), m_soundShaping( this ), m_arpeggiator( this ), m_chordCreator( this ), - m_midiIO( this, m_midiPort ), m_piano( this ) { m_baseNoteModel.setTrack( this ); @@ -145,7 +145,6 @@ instrumentTrack::instrumentTrack( trackContainer * _tc ) : instrumentTrack::~instrumentTrack() { engine::getMixer()->removePlayHandles( this ); - engine::getMixer()->getMIDIClient()->removePort( m_midiPort ); delete m_instrument; } @@ -339,7 +338,7 @@ void instrumentTrack::processOutEvent( const midiEvent & _me, break; } // if appropriate, midi-port does futher routing - m_midiPort->processOutEvent( _me, _time ); + m_midiPort.processOutEvent( _me, _time ); } @@ -466,7 +465,7 @@ void instrumentTrack::setName( const QString & _new_name ) } track::setName( _new_name ); - m_midiPort->setName( name() ); + m_midiPort.setName( name() ); m_audioPort.setName( name() ); emit nameChanged(); @@ -675,7 +674,7 @@ void instrumentTrack::saveTrackSpecificSettings( QDomDocument & _doc, m_soundShaping.saveState( _doc, _this ); m_chordCreator.saveState( _doc, _this ); m_arpeggiator.saveState( _doc, _this ); - m_midiIO.saveState( _doc, _this ); + m_midiPort.saveState( _doc, _this ); m_audioPort.getEffects()->saveState( _doc, _this ); if( getHook() ) { @@ -743,9 +742,9 @@ void instrumentTrack::loadTrackSpecificSettings( const QDomElement & _this ) { m_arpeggiator.restoreState( node.toElement() ); } - else if( m_midiIO.nodeName() == node.nodeName() ) + else if( m_midiPort.nodeName() == node.nodeName() ) { - m_midiIO.restoreState( node.toElement() ); + m_midiPort.restoreState( node.toElement() ); } else if( m_audioPort.getEffects()->nodeName() == node.nodeName() ) @@ -830,7 +829,9 @@ QQueue instrumentTrackView::s_windows; instrumentTrackView::instrumentTrackView( instrumentTrack * _it, trackContainerView * _tcv ) : trackView( _it, _tcv ), - m_window( NULL ) + m_window( NULL ), + m_readablePortsMenu( NULL ), + m_writablePortsMenu( NULL ) { setAcceptDrops( TRUE ); setFixedHeight( 32 ); @@ -854,6 +855,32 @@ instrumentTrackView::instrumentTrackView( instrumentTrack * _it, m_tswMidiMenu = new QMenu( tsw_midi ); tsw_midi->setMenu( m_tswMidiMenu ); + // sequenced MIDI? + if( !engine::getMixer()->getMIDIClient()->isRaw() ) + { + m_readablePortsMenu = new midiPortMenu( midiPort::Input ); + m_writablePortsMenu = new midiPortMenu( midiPort::Output ); + m_readablePortsMenu->setModel( &_it->m_midiPort ); + m_writablePortsMenu->setModel( &_it->m_midiPort ); + m_midiInputAction = m_tswMidiMenu->addMenu( + m_readablePortsMenu ); + m_midiOutputAction = m_tswMidiMenu->addMenu( + m_writablePortsMenu ); + } + else + { + m_midiInputAction = m_tswMidiMenu->addAction( "" ); + connect( m_midiInputAction, SIGNAL( changed() ), this, + SLOT( midiInSelected() ) ); + m_midiOutputAction = m_tswMidiMenu->addAction( "" ); + connect( m_midiOutputAction, SIGNAL( changed() ), this, + SLOT( midiOutSelected() ) ); + connect( &_it->m_midiPort, SIGNAL( modeChanged() ), + this, SLOT( midiConfigChanged() ) ); + } + + m_midiInputAction->setText( tr( "MIDI input" ) ); + m_midiOutputAction->setText( tr( "MIDI output" ) ); m_tswActivityIndicator = new fadeButton( QColor( 96, 96, 96 ), QColor( 255, 204, 0 ), @@ -871,41 +898,6 @@ instrumentTrackView::instrumentTrackView( instrumentTrack * _it, m_tswInstrumentTrackButton->setGeometry( 64, 2, 144, 28 ); m_tswInstrumentTrackButton->show(); -/* if( m_midiWidget->m_readablePorts ) - { - m_midiInputAction = m_tswMidiMenu->addMenu( - m_midiWidget->m_readablePorts ); - } - else - { - m_midiInputAction = m_tswMidiMenu->addAction( "" ); - connect( m_midiInputAction, SIGNAL( changed() ), this, - SLOT( midiInSelected() ) ); - } - if( m_midiWidget->m_writeablePorts ) - { - m_midiOutputAction = m_tswMidiMenu->addMenu( - m_midiWidget->m_writeablePorts ); - } - else - { - m_midiOutputAction = m_tswMidiMenu->addAction( "" ); - connect( m_midiOutputAction, SIGNAL( changed() ), this, - SLOT( midiOutSelected() ) ); - } - m_midiInputAction->setText( tr( "MIDI input" ) ); - m_midiOutputAction->setText( tr( "MIDI output" ) ); - if( m_midiWidget->m_readablePorts == NULL || - m_midiWidget->m_writeablePorts == NULL ) - { - connect( m_midiWidget->m_sendCheckBox, - SIGNAL( toggled( bool ) ), - this, SLOT( midiConfigChanged( bool ) ) ); - connect( m_midiWidget->m_receiveCheckBox, - SIGNAL( toggled( bool ) ), - this, SLOT( midiConfigChanged( bool ) ) ); - }*/ - setModel( _it ); connect( m_tswInstrumentTrackButton, SIGNAL( toggled( bool ) ), @@ -1029,6 +1021,36 @@ void instrumentTrackView::updateName( void ) + +void instrumentTrackView::midiInSelected( void ) +{ + m_midiInputAction->setChecked( !m_midiInputAction->isChecked() ); + model()->m_midiPort.setReadable( m_midiInputAction->isChecked() ); +} + + + + +void instrumentTrackView::midiOutSelected( void ) +{ + m_midiOutputAction->setChecked( !m_midiOutputAction->isChecked() ); + model()->m_midiPort.setWritable( m_midiOutputAction->isChecked() ); +} + + + + +void instrumentTrackView::midiConfigChanged( void ) +{ + m_midiInputAction->setChecked( model()->m_midiPort.isReadable() ); + m_midiOutputAction->setChecked( model()->m_midiPort.isWritable() ); +} + + + + + + class fxLineLcdSpinBox : public lcdSpinBox { public: @@ -1052,9 +1074,7 @@ instrumentTrackWindow::instrumentTrackWindow( instrumentTrackView * _itv ) : modelView( NULL ), m_track( _itv->model() ), m_itv( _itv ), - m_instrumentView( NULL ), - m_midiInputAction( NULL ), - m_midiOutputAction( NULL ) + m_instrumentView( NULL ) { setAcceptDrops( TRUE ); @@ -1130,7 +1150,9 @@ instrumentTrackWindow::instrumentTrackWindow( instrumentTrackView * _itv ) : instrument_functions ); m_arpView= new arpeggiatorView( &m_track->m_arpeggiator, instrument_functions ); - m_midiView = new instrumentMidiIOView( m_tabWidget ); + m_midiView = new instrumentMidiIOView( m_itv->m_readablePortsMenu, + m_itv->m_writablePortsMenu, + m_tabWidget ); m_effectView = new effectRackView( m_track->m_audioPort.getEffects(), m_tabWidget ); m_tabWidget->addTab( m_ssView, tr( "ENV/LFO" ), 1 ); @@ -1146,40 +1168,6 @@ instrumentTrackWindow::instrumentTrackWindow( instrumentTrackView * _itv ) : vlayout->addWidget( m_tabWidget ); vlayout->addWidget( m_pianoView ); - if( m_midiView->m_readablePorts ) - { - m_midiInputAction = m_itv->m_tswMidiMenu->addMenu( - m_midiView->m_readablePorts ); - } - else - { - m_midiInputAction = m_itv->m_tswMidiMenu->addAction( "" ); - connect( m_midiInputAction, SIGNAL( changed() ), this, - SLOT( midiInSelected() ) ); - } - if( m_midiView->m_writeablePorts ) - { - m_midiOutputAction = m_itv->m_tswMidiMenu->addMenu( - m_midiView->m_writeablePorts ); - } - else - { - m_midiOutputAction = m_itv->m_tswMidiMenu->addAction( "" ); - connect( m_midiOutputAction, SIGNAL( changed() ), this, - SLOT( midiOutSelected() ) ); - } - m_midiInputAction->setText( tr( "MIDI input" ) ); - m_midiOutputAction->setText( tr( "MIDI output" ) ); - if( m_midiView->m_readablePorts == NULL || - m_midiView->m_writeablePorts == NULL ) - { - connect( m_midiView->m_sendCheckBox, - SIGNAL( toggled( bool ) ), - this, SLOT( midiConfigChanged( bool ) ) ); - connect( m_midiView->m_receiveCheckBox, - SIGNAL( toggled( bool ) ), - this, SLOT( midiConfigChanged( bool ) ) ); - } setModel( _itv->model() ); @@ -1241,9 +1229,18 @@ void instrumentTrackWindow::modelChanged( void ) m_ssView->setModel( &m_track->m_soundShaping ); m_chordView->setModel( &m_track->m_chordCreator ); m_arpView->setModel( &m_track->m_arpeggiator ); - m_midiView->setModel( &m_track->m_midiIO ); + m_midiView->setModel( &m_track->m_midiPort ); m_effectView->setModel( m_track->m_audioPort.getEffects() ); updateName(); + + if( m_itv->m_readablePortsMenu != NULL ) + { + m_itv->m_readablePortsMenu->setModel( &m_track->m_midiPort ); + } + if( m_itv->m_writablePortsMenu != NULL ) + { + m_itv->m_writablePortsMenu->setModel( &m_track->m_midiPort ); + } } @@ -1435,32 +1432,6 @@ void instrumentTrackWindow::loadSettings( const QDomElement & _this ) -void instrumentTrackWindow::midiInSelected( void ) -{ - m_midiInputAction->setChecked( !m_midiInputAction->isChecked() ); - m_midiView->m_receiveCheckBox->setChecked( - m_midiInputAction->isChecked() ); -} - - - -void instrumentTrackWindow::midiOutSelected( void ) -{ - m_midiOutputAction->setChecked( !m_midiOutputAction->isChecked() ); - m_midiView->m_sendCheckBox->setChecked( - m_midiOutputAction->isChecked() ); -} - - - - -void instrumentTrackWindow::midiConfigChanged( bool ) -{ - m_midiInputAction->setChecked( - m_midiView->m_receiveCheckBox->model()->value() ); - m_midiOutputAction->setChecked( - m_midiView->m_sendCheckBox->model()->value() ); -}