From 374abf22983374ce577c0a84b064864041531b3a Mon Sep 17 00:00:00 2001 From: IanCaio Date: Fri, 10 Jul 2020 18:58:32 -0300 Subject: [PATCH 01/40] First commit This branch will be used to implement a new feature to LMMS, where MIDI CC messages support will be added through the use of a rack holding knobs representing each MIDI controller. The changes to values of those knobs will trigger MIDI CC messages to the corresponding track. There will be the possibility of automating the values. Summary of changes: - Creates a new icon to be used on the MIDI CC rack window. - Adds the MIDI CC rack window as a new class. - Very basic window toggling functionality. - Updates CMakeList to compile this new .cpp file. --- data/themes/classic/midi_cc_rack.png | Bin 0 -> 667 bytes data/themes/default/midi_cc_rack.png | Bin 0 -> 667 bytes include/GuiApplication.h | 3 ++ include/MainWindow.h | 1 + include/MidiCCRackView.h | 30 ++++++++++++++++++++ src/gui/CMakeLists.txt | 1 + src/gui/GuiApplication.cpp | 5 ++++ src/gui/MainWindow.cpp | 18 ++++++++++++ src/gui/widgets/MidiCCRackView.cpp | 40 +++++++++++++++++++++++++++ 9 files changed, 98 insertions(+) create mode 100644 data/themes/classic/midi_cc_rack.png create mode 100644 data/themes/default/midi_cc_rack.png create mode 100644 include/MidiCCRackView.h create mode 100644 src/gui/widgets/MidiCCRackView.cpp diff --git a/data/themes/classic/midi_cc_rack.png b/data/themes/classic/midi_cc_rack.png new file mode 100644 index 0000000000000000000000000000000000000000..6ec1dd2ee0a011bc95791c6265102e76f2593829 GIT binary patch literal 667 zcmV;M0%ZM(P)d0w_sD zK~y-)t(84!6hRb#zqcE?3l|I~XOxM-MuL$@EUZjpBZ8uhkV+$nSfsPj!X`~DENs$Q z*!WjjsH6}g7Ajh3C0f`-vNtoEOVEJ9Aa}dZW)2Q;hJSr8tfk1z=@mrCO;}o&skI z7XD(4nOs|2+m~h8GB8=dJ&6D+mC8bpwN&+HmSw|04Y&ZLz*~SU%N_*TCNK-sTCLWQ zh|B@oBJxfejmCi}ioOFeaLX8TyL(CJ+=Qx*i^w+cGNkAH=;-K+Zq9puw%u+gSZi-M z=hQj3)oeBgijwV|dlr%+XohIq9I3SWM(j01>( zp%AYZL9JG6PgjX;lnHAg(VKd z;WA;POjxhi*MUD}Tu1mdvDfM0;9 z>ioYzk|aac+Iip+puk|B=hy$!Nr%1nbJ5t?*bh}*2wR)+-rrA>emJpn8MrzM=6c<=84S9@%EFYr4|JXyea=^j~Y&jHs&{_gZlsg002ovPDHLkV1o8M BCJq1q literal 0 HcmV?d00001 diff --git a/data/themes/default/midi_cc_rack.png b/data/themes/default/midi_cc_rack.png new file mode 100644 index 0000000000000000000000000000000000000000..6ec1dd2ee0a011bc95791c6265102e76f2593829 GIT binary patch literal 667 zcmV;M0%ZM(P)d0w_sD zK~y-)t(84!6hRb#zqcE?3l|I~XOxM-MuL$@EUZjpBZ8uhkV+$nSfsPj!X`~DENs$Q z*!WjjsH6}g7Ajh3C0f`-vNtoEOVEJ9Aa}dZW)2Q;hJSr8tfk1z=@mrCO;}o&skI z7XD(4nOs|2+m~h8GB8=dJ&6D+mC8bpwN&+HmSw|04Y&ZLz*~SU%N_*TCNK-sTCLWQ zh|B@oBJxfejmCi}ioOFeaLX8TyL(CJ+=Qx*i^w+cGNkAH=;-K+Zq9puw%u+gSZi-M z=hQj3)oeBgijwV|dlr%+XohIq9I3SWM(j01>( zp%AYZL9JG6PgjX;lnHAg(VKd z;WA;POjxhi*MUD}Tu1mdvDfM0;9 z>ioYzk|aac+Iip+puk|B=hy$!Nr%1nbJ5t?*bh}*2wR)+-rrA>emJpn8MrzM=6c<=84S9@%EFYr4|JXyea=^j~Y&jHs&{_gZlsg002ovPDHLkV1o8M BCJq1q literal 0 HcmV?d00001 diff --git a/include/GuiApplication.h b/include/GuiApplication.h index 8b4284c026b..0752dffd6e4 100644 --- a/include/GuiApplication.h +++ b/include/GuiApplication.h @@ -39,6 +39,7 @@ class MainWindow; class PianoRollWindow; class ProjectNotes; class SongEditorWindow; +class MidiCCRackView; class LMMS_EXPORT GuiApplication : public QObject { @@ -57,6 +58,7 @@ class LMMS_EXPORT GuiApplication : public QObject ProjectNotes* getProjectNotes() { return m_projectNotes; } AutomationEditorWindow* automationEditor() { return m_automationEditor; } ControllerRackView* getControllerRackView() { return m_controllerRackView; } + MidiCCRackView* getMidiCCRackView() { return m_midiCCRackView; } public slots: void displayInitProgress(const QString &msg); @@ -75,6 +77,7 @@ private slots: PianoRollWindow* m_pianoRoll; ProjectNotes* m_projectNotes; ControllerRackView* m_controllerRackView; + MidiCCRackView* m_midiCCRackView; QLabel* m_loadingProgressLabel; }; diff --git a/include/MainWindow.h b/include/MainWindow.h index c894ef4f0e4..5b0dfd252e8 100644 --- a/include/MainWindow.h +++ b/include/MainWindow.h @@ -155,6 +155,7 @@ public slots: void toggleFxMixerWin(); void togglePianoRollWin(); void toggleControllerRack(); + void toggleMidiCCRack(); void updatePlayPauseIcons(); diff --git a/include/MidiCCRackView.h b/include/MidiCCRackView.h new file mode 100644 index 00000000000..527373add3e --- /dev/null +++ b/include/MidiCCRackView.h @@ -0,0 +1,30 @@ +#ifndef MIDI_CC_RACK_VIEW_H +#define MIDI_CC_RACK_VIEW_H + +#include +#include + +#include "SerializingObject.h" +#include "lmms_basics.h" + +class MidiCCRackView : public QWidget, public SerializingObject +{ + Q_OBJECT +public: + MidiCCRackView(); + virtual ~MidiCCRackView(); + + void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override; + void loadSettings( const QDomElement & _this ) override; + + inline QString nodeName() const override + { + return "MidiCCRackView"; + } + +//protected: +// void closeEvent( QCloseEvent * _ce ) override; + +}; + +#endif diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index 81e588c6659..fb81c4b2a59 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -77,6 +77,7 @@ SET(LMMS_SRCS gui/widgets/ControlLayout.cpp gui/widgets/LinkedModelGroupViews.cpp gui/widgets/MeterDialog.cpp + gui/widgets/MidiCCRackView.cpp gui/widgets/MidiPortMenu.cpp gui/widgets/NStateButton.cpp gui/widgets/Oscilloscope.cpp diff --git a/src/gui/GuiApplication.cpp b/src/gui/GuiApplication.cpp index fb2e3eae376..54ccef52d7b 100644 --- a/src/gui/GuiApplication.cpp +++ b/src/gui/GuiApplication.cpp @@ -38,6 +38,7 @@ #include "PianoRoll.h" #include "ProjectNotes.h" #include "SongEditor.h" +#include "MidiCCRackView.h" #include #include @@ -135,6 +136,10 @@ GuiApplication::GuiApplication() m_controllerRackView = new ControllerRackView; connect(m_controllerRackView, SIGNAL(destroyed(QObject*)), this, SLOT(childDestroyed(QObject*))); + displayInitProgress(tr("Preparing midi cc rack")); + m_midiCCRackView = new MidiCCRackView; + connect(m_midiCCRackView, SIGNAL(destroyed(QObject*)), this, SLOT(childDestroyed(QObject*))); + displayInitProgress(tr("Preparing project notes")); m_projectNotes = new ProjectNotes; connect(m_projectNotes, SIGNAL(destroyed(QObject*)), this, SLOT(childDestroyed(QObject*))); diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index 2be265e047b..70683458863 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -42,6 +42,7 @@ #include "AutomationEditor.h" #include "BBEditor.h" #include "ControllerRackView.h" +#include "MidiCCRackView.h" #include "embed.h" #include "Engine.h" #include "ExportProjectDialog.h" @@ -534,6 +535,14 @@ void MainWindow::finalize() m_toolBar ); project_notes_window->setShortcut( Qt::Key_F11 ); + ToolButton * midi_cc_rack_window = new ToolButton( + embed::getIconPixmap( "midi_cc_rack" ), + tr( "Show/hide midi cc rack") + + " (F12)", + this, SLOT( toggleMidiCCRack() ), + m_toolBar ); + midi_cc_rack_window->setShortcut( Qt::Key_F12 ); + m_toolBarLayout->addWidget( song_editor_window, 1, 1 ); m_toolBarLayout->addWidget( bb_editor_window, 1, 2 ); m_toolBarLayout->addWidget( piano_roll_window, 1, 3 ); @@ -541,6 +550,7 @@ void MainWindow::finalize() m_toolBarLayout->addWidget( fx_mixer_window, 1, 5 ); m_toolBarLayout->addWidget( controllers_window, 1, 6 ); m_toolBarLayout->addWidget( project_notes_window, 1, 7 ); + m_toolBarLayout->addWidget( midi_cc_rack_window, 1, 8 ); m_toolBarLayout->setColumnStretch( 100, 1 ); // setup-dialog opened before? @@ -1219,6 +1229,14 @@ void MainWindow::toggleControllerRack() +void MainWindow::toggleMidiCCRack() +{ + toggleWindow( gui->getMidiCCRackView() ); +} + + + + void MainWindow::updatePlayPauseIcons() { gui->songEditor()->setPauseIcon( false ); diff --git a/src/gui/widgets/MidiCCRackView.cpp b/src/gui/widgets/MidiCCRackView.cpp new file mode 100644 index 00000000000..5a66efa0250 --- /dev/null +++ b/src/gui/widgets/MidiCCRackView.cpp @@ -0,0 +1,40 @@ +#include // For Qt::WindowFlags +#include +#include + +#include "MidiCCRackView.h" +#include "GuiApplication.h" +#include "MainWindow.h" +#include "embed.h" + + +MidiCCRackView::MidiCCRackView() : + QWidget() +{ + setWindowIcon( embed::getIconPixmap( "midi_cc_rack" ) ); + setWindowTitle( tr("Midi CC Rack") ); + + QMdiSubWindow * subWin = gui->mainWindow()->addWindowedWidget( this ); + + // Remove maximize button + Qt::WindowFlags flags = subWin->windowFlags(); + flags &= ~Qt::WindowMaximizeButtonHint; + subWin->setWindowFlags( flags ); + + subWin->setAttribute( Qt::WA_DeleteOnClose, false ); + subWin->move( 780, 50 ); + subWin->resize( 350, 200 ); +} + +MidiCCRackView::~MidiCCRackView() +{ +} + +void MidiCCRackView::saveSettings( QDomDocument & _doc, + QDomElement & _this ) +{ +} + +void MidiCCRackView::loadSettings( const QDomElement & _this ) +{ +} From f1603eafe60d44de28bf21d5869b90cfb9f17ea1 Mon Sep 17 00:00:00 2001 From: IanCaio Date: Fri, 10 Jul 2020 21:02:49 -0300 Subject: [PATCH 02/40] Updates the MIDI CC Rack GUI Keeps working on the GUI from the MIDI CC Rack. Now we have a track tool bar where we have a label and a combobox where the Instrument tracks will be listed. Below it we have a GroupBox where later the MIDI CC knobs will be added. --- src/gui/widgets/MidiCCRackView.cpp | 34 ++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/gui/widgets/MidiCCRackView.cpp b/src/gui/widgets/MidiCCRackView.cpp index 5a66efa0250..6f2b0700e0e 100644 --- a/src/gui/widgets/MidiCCRackView.cpp +++ b/src/gui/widgets/MidiCCRackView.cpp @@ -1,11 +1,16 @@ #include // For Qt::WindowFlags #include #include +#include +#include +#include #include "MidiCCRackView.h" #include "GuiApplication.h" #include "MainWindow.h" #include "embed.h" +#include "ComboBox.h" +#include "GroupBox.h" MidiCCRackView::MidiCCRackView() : @@ -21,9 +26,38 @@ MidiCCRackView::MidiCCRackView() : flags &= ~Qt::WindowMaximizeButtonHint; subWin->setWindowFlags( flags ); + // Adjust window attributes, sizing and position subWin->setAttribute( Qt::WA_DeleteOnClose, false ); subWin->move( 780, 50 ); subWin->resize( 350, 200 ); + subWin->setFixedWidth( 350 ); + subWin->setMinimumHeight( 200 ); + + // Main window layout + QVBoxLayout *mainLayout = new QVBoxLayout( this ); + + // Track Selector Layout - Here we select which track we are sending CC messages to + // We use a widget to be able to make this layout have a fixed height + QWidget *trackToolBar = new QWidget(); + QHBoxLayout *trackToolBarLayout = new QHBoxLayout(trackToolBar); + QLabel *trackLabel = new QLabel( tr("Track: ") ); + ComboBox *trackComboBox = new ComboBox(); + + trackToolBarLayout->addWidget(trackLabel); + trackToolBarLayout->addWidget(trackComboBox); + trackToolBarLayout->setStretchFactor( trackLabel, 1 ); + trackToolBarLayout->setStretchFactor( trackComboBox, 2 ); + trackToolBar->setFixedHeight(40); + + // Knobs Layout - Here we have the MIDI CC controller knobs for the selected track + QVBoxLayout *knobsLayout = new QVBoxLayout(); + GroupBox *knobsGroupBox = new GroupBox( tr("MIDI CC Knobs:") ); + + knobsLayout->addWidget(knobsGroupBox); + + // Adding both to the main layout + mainLayout->addWidget(trackToolBar); + mainLayout->addLayout(knobsLayout); } MidiCCRackView::~MidiCCRackView() From 53fe0d046343cff186cc455a53fdd5d6f967680a Mon Sep 17 00:00:00 2001 From: IanCaio Date: Sat, 11 Jul 2020 00:56:07 -0300 Subject: [PATCH 03/40] Keeps working on the MIDI CC Rack GUI This commit basically finishes the basic GUI of the MIDI CC Rack, still not functional. It adds a scrollable area to hold the knobs and a knob for each possible CC controller. --- src/gui/widgets/MidiCCRackView.cpp | 37 +++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/src/gui/widgets/MidiCCRackView.cpp b/src/gui/widgets/MidiCCRackView.cpp index 6f2b0700e0e..fb08ac7b54f 100644 --- a/src/gui/widgets/MidiCCRackView.cpp +++ b/src/gui/widgets/MidiCCRackView.cpp @@ -3,7 +3,9 @@ #include #include #include +#include #include +#include #include "MidiCCRackView.h" #include "GuiApplication.h" @@ -11,6 +13,7 @@ #include "embed.h" #include "ComboBox.h" #include "GroupBox.h" +#include "Knob.h" MidiCCRackView::MidiCCRackView() : @@ -39,7 +42,7 @@ MidiCCRackView::MidiCCRackView() : // Track Selector Layout - Here we select which track we are sending CC messages to // We use a widget to be able to make this layout have a fixed height QWidget *trackToolBar = new QWidget(); - QHBoxLayout *trackToolBarLayout = new QHBoxLayout(trackToolBar); + QHBoxLayout *trackToolBarLayout = new QHBoxLayout( trackToolBar ); QLabel *trackLabel = new QLabel( tr("Track: ") ); ComboBox *trackComboBox = new ComboBox(); @@ -49,15 +52,37 @@ MidiCCRackView::MidiCCRackView() : trackToolBarLayout->setStretchFactor( trackComboBox, 2 ); trackToolBar->setFixedHeight(40); - // Knobs Layout - Here we have the MIDI CC controller knobs for the selected track - QVBoxLayout *knobsLayout = new QVBoxLayout(); + // Knobs GroupBox - Here we have the MIDI CC controller knobs for the selected track GroupBox *knobsGroupBox = new GroupBox( tr("MIDI CC Knobs:") ); - knobsLayout->addWidget(knobsGroupBox); + // Layout to keep scrollable area under the GroupBox header + QVBoxLayout *knobsGroupBoxLayout = new QVBoxLayout(); + knobsGroupBoxLayout->setContentsMargins( 5, 16, 5, 5 ); - // Adding both to the main layout + knobsGroupBox->setLayout(knobsGroupBoxLayout); + + // Scrollable area + widget + its layout that will have all the knobs + QScrollArea *knobsScrollArea = new QScrollArea(); + QWidget *knobsArea = new QWidget(); + QGridLayout *knobsAreaLayout = new QGridLayout(); + + knobsArea->setLayout( knobsAreaLayout ); + knobsScrollArea->setWidget( knobsArea ); + knobsScrollArea->setWidgetResizable( true ); + + knobsGroupBoxLayout->addWidget(knobsScrollArea); + + // Adds the controller knobs + Knob *k; + for(int i = 0; i < 127; i++){ + k = new Knob( knobBright_26 ); + k->setLabel( QString("CC %1").arg(QString::number(i + 1)) ); + knobsAreaLayout->addWidget( k, i/3, i%3 ); + } + + // Adding everything to the main layout mainLayout->addWidget(trackToolBar); - mainLayout->addLayout(knobsLayout); + mainLayout->addWidget(knobsGroupBox); } MidiCCRackView::~MidiCCRackView() From 755cf1204add52d0ddd5b96c3131276da90128b0 Mon Sep 17 00:00:00 2001 From: IanCaio Date: Sat, 11 Jul 2020 11:30:54 -0300 Subject: [PATCH 04/40] Add class members -Adds class members to hold the CC knobs and the track combobox. -Stores the number of controllers on a constant. -Changes vertical size of MIDI CC Rack window. --- include/MidiCCRackView.h | 8 ++++++++ src/gui/widgets/MidiCCRackView.cpp | 19 +++++++++---------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/include/MidiCCRackView.h b/include/MidiCCRackView.h index 527373add3e..89f715ecbe9 100644 --- a/include/MidiCCRackView.h +++ b/include/MidiCCRackView.h @@ -6,6 +6,10 @@ #include "SerializingObject.h" #include "lmms_basics.h" +#include "ComboBox.h" +#include "Knob.h" + +const int MIDI_CC_MAX_CONTROLLERS = 127; class MidiCCRackView : public QWidget, public SerializingObject { @@ -22,6 +26,10 @@ class MidiCCRackView : public QWidget, public SerializingObject return "MidiCCRackView"; } +private: + ComboBox *m_trackComboBox; + Knob *m_controllerKnob[MIDI_CC_MAX_CONTROLLERS]; // Holds the knob widgets for each controller + //protected: // void closeEvent( QCloseEvent * _ce ) override; diff --git a/src/gui/widgets/MidiCCRackView.cpp b/src/gui/widgets/MidiCCRackView.cpp index fb08ac7b54f..237bc9ad99f 100644 --- a/src/gui/widgets/MidiCCRackView.cpp +++ b/src/gui/widgets/MidiCCRackView.cpp @@ -32,9 +32,9 @@ MidiCCRackView::MidiCCRackView() : // Adjust window attributes, sizing and position subWin->setAttribute( Qt::WA_DeleteOnClose, false ); subWin->move( 780, 50 ); - subWin->resize( 350, 200 ); + subWin->resize( 350, 300 ); subWin->setFixedWidth( 350 ); - subWin->setMinimumHeight( 200 ); + subWin->setMinimumHeight( 300 ); // Main window layout QVBoxLayout *mainLayout = new QVBoxLayout( this ); @@ -44,12 +44,12 @@ MidiCCRackView::MidiCCRackView() : QWidget *trackToolBar = new QWidget(); QHBoxLayout *trackToolBarLayout = new QHBoxLayout( trackToolBar ); QLabel *trackLabel = new QLabel( tr("Track: ") ); - ComboBox *trackComboBox = new ComboBox(); + m_trackComboBox = new ComboBox(); trackToolBarLayout->addWidget(trackLabel); - trackToolBarLayout->addWidget(trackComboBox); + trackToolBarLayout->addWidget(m_trackComboBox); trackToolBarLayout->setStretchFactor( trackLabel, 1 ); - trackToolBarLayout->setStretchFactor( trackComboBox, 2 ); + trackToolBarLayout->setStretchFactor( m_trackComboBox, 2 ); trackToolBar->setFixedHeight(40); // Knobs GroupBox - Here we have the MIDI CC controller knobs for the selected track @@ -73,11 +73,10 @@ MidiCCRackView::MidiCCRackView() : knobsGroupBoxLayout->addWidget(knobsScrollArea); // Adds the controller knobs - Knob *k; - for(int i = 0; i < 127; i++){ - k = new Knob( knobBright_26 ); - k->setLabel( QString("CC %1").arg(QString::number(i + 1)) ); - knobsAreaLayout->addWidget( k, i/3, i%3 ); + for(int i = 0; i < MIDI_CC_MAX_CONTROLLERS; i++){ + m_controllerKnob[i] = new Knob( knobBright_26 ); + m_controllerKnob[i]->setLabel( QString("CC %1").arg(QString::number(i + 1)) ); + knobsAreaLayout->addWidget( m_controllerKnob[i], i/3, i%3 ); } // Adding everything to the main layout From 7599fecb295cad92b3287172698f3a262db93564 Mon Sep 17 00:00:00 2001 From: IanCaio Date: Sat, 11 Jul 2020 17:54:41 -0300 Subject: [PATCH 05/40] Starts implementing the track ComboBox syncing The MIDI CC Rack ComboBox containing the available instrument tracks now updates itself to be in sync with the tracks on the Song Editor and BB Editor. Summary of changes: - Creates a ComboBoxModel to hold the tracks names for the ComboBox. - Adds two new signals to the TrackContainer class: trackRemoved and trackRenamed. The trackRenamed signal is connected to the nameChanged signal of each track added to the TrackContainer. - Connects the trackAdded, trackRemoved and trackRenamed signals from both the song editor and BB editor to a slot method that will update the ComboBoxModel with the appropriate track names. - Added the updateTracksComboBox method that will clear the model and fill it again with the updated track names from both the song editor and BB editor. To do: - Make sure the ComboBox reorder the tracks if we drag the TrackContainerView widget on the song editor or BB editor (in other words, reorder the combobox list if we reorder the tracks). --- include/MidiCCRackView.h | 6 ++++ include/TrackContainer.h | 2 ++ src/core/TrackContainer.cpp | 5 +++ src/gui/widgets/MidiCCRackView.cpp | 57 ++++++++++++++++++++++++++++++ 4 files changed, 70 insertions(+) diff --git a/include/MidiCCRackView.h b/include/MidiCCRackView.h index 89f715ecbe9..631663bc7de 100644 --- a/include/MidiCCRackView.h +++ b/include/MidiCCRackView.h @@ -7,6 +7,7 @@ #include "SerializingObject.h" #include "lmms_basics.h" #include "ComboBox.h" +#include "ComboBoxModel.h" #include "Knob.h" const int MIDI_CC_MAX_CONTROLLERS = 127; @@ -26,8 +27,13 @@ class MidiCCRackView : public QWidget, public SerializingObject return "MidiCCRackView"; } +public slots: + void updateTracksComboBox(); + private: ComboBox *m_trackComboBox; + ComboBoxModel *m_trackComboBoxModel; + Knob *m_controllerKnob[MIDI_CC_MAX_CONTROLLERS]; // Holds the knob widgets for each controller //protected: diff --git a/include/TrackContainer.h b/include/TrackContainer.h index fd853a73c1e..e89f0b20fab 100644 --- a/include/TrackContainer.h +++ b/include/TrackContainer.h @@ -97,6 +97,8 @@ class LMMS_EXPORT TrackContainer : public Model, public JournallingObject signals: void trackAdded( Track * _track ); + void trackRemoved(); + void trackRenamed(); protected: static AutomatedValueMap automatedValuesFromTracks(const TrackList &tracks, MidiTime timeStart, int tcoNum = -1); diff --git a/src/core/TrackContainer.cpp b/src/core/TrackContainer.cpp index 95dd46f298c..1aabf279094 100644 --- a/src/core/TrackContainer.cpp +++ b/src/core/TrackContainer.cpp @@ -181,6 +181,9 @@ void TrackContainer::addTrack( Track * _track ) m_tracksMutex.unlock(); _track->unlock(); emit trackAdded( _track ); + + connect( _track, SIGNAL( nameChanged() ), + this, SIGNAL( trackRenamed() ) ); } } @@ -207,6 +210,8 @@ void TrackContainer::removeTrack( Track * _track ) { Engine::getSong()->setModified(); } + + emit trackRemoved(); } } diff --git a/src/gui/widgets/MidiCCRackView.cpp b/src/gui/widgets/MidiCCRackView.cpp index 237bc9ad99f..11bc142f9b2 100644 --- a/src/gui/widgets/MidiCCRackView.cpp +++ b/src/gui/widgets/MidiCCRackView.cpp @@ -12,8 +12,14 @@ #include "MainWindow.h" #include "embed.h" #include "ComboBox.h" +#include "ComboBoxModel.h" #include "GroupBox.h" #include "Knob.h" +#include "Track.h" +#include "TrackContainer.h" +#include "BBTrackContainer.h" +#include "Engine.h" +#include "Song.h" MidiCCRackView::MidiCCRackView() : @@ -45,6 +51,8 @@ MidiCCRackView::MidiCCRackView() : QHBoxLayout *trackToolBarLayout = new QHBoxLayout( trackToolBar ); QLabel *trackLabel = new QLabel( tr("Track: ") ); m_trackComboBox = new ComboBox(); + m_trackComboBoxModel = new ComboBoxModel(); + m_trackComboBox->setModel(m_trackComboBoxModel); trackToolBarLayout->addWidget(trackLabel); trackToolBarLayout->addWidget(m_trackComboBox); @@ -79,6 +87,24 @@ MidiCCRackView::MidiCCRackView() : knobsAreaLayout->addWidget( m_controllerKnob[i], i/3, i%3 ); } + // Connections are made to make sure the track ComboBox is updated when tracks are + // added, removed or renamed + // On the song editor: + connect( Engine::getSong() , SIGNAL( trackAdded(Track *) ), + this, SLOT( updateTracksComboBox() ) ); + connect( Engine::getSong() , SIGNAL( trackRemoved() ), + this, SLOT( updateTracksComboBox() ) ); + connect( Engine::getSong() , SIGNAL( trackRenamed() ), + this, SLOT( updateTracksComboBox() ) ); + // On the BB editor: + connect( Engine::getBBTrackContainer() , SIGNAL( trackAdded(Track *) ), + this, SLOT( updateTracksComboBox() ) ); + connect( Engine::getBBTrackContainer() , SIGNAL( trackRemoved() ), + this, SLOT( updateTracksComboBox() ) ); + connect( Engine::getBBTrackContainer() , SIGNAL( trackRenamed() ), + this, SLOT( updateTracksComboBox() ) ); + + // Adding everything to the main layout mainLayout->addWidget(trackToolBar); mainLayout->addWidget(knobsGroupBox); @@ -88,6 +114,37 @@ MidiCCRackView::~MidiCCRackView() { } +void MidiCCRackView::updateTracksComboBox() +{ + // Reset the combo box model and fill it with instrument tracks from the song editor + m_trackComboBoxModel->clear(); + + TrackContainer::TrackList songEditorTracks; + songEditorTracks += Engine::getSong()->tracks(); + int songEditorID = 1; + + TrackContainer::TrackList bbEditorTracks; + bbEditorTracks += Engine::getBBTrackContainer()->tracks(); + int bbEditorID = 1; + + for(Track *t: songEditorTracks) + { + if( t->type() == Track::InstrumentTrack ) + { + m_trackComboBoxModel->addItem("SongEditor: " + QString::number(songEditorID) + ". " + t->name()); + ++songEditorID; + } + } + for(Track *t: bbEditorTracks) + { + if( t->type() == Track::InstrumentTrack ) + { + m_trackComboBoxModel->addItem("BBEditor: " + QString::number(bbEditorID) + ". " + t->name()); + ++bbEditorID; + } + } +} + void MidiCCRackView::saveSettings( QDomDocument & _doc, QDomElement & _this ) { From fb713755c96febcf0313c534d1230b714ed147f2 Mon Sep 17 00:00:00 2001 From: IanCaio Date: Sun, 12 Jul 2020 09:51:38 -0300 Subject: [PATCH 06/40] Updates tracks ComboBox when tracks are moved Now when tracks are moved inside the song editor and BB editor, they get reordered at the ComboBox as well. Summary of changes: - Added a movedTrackView signal to TrackContainerView class, which will be emitted when a track is moved. - Connects this signal inherited from the song editor and BB editor, so it triggers the tracks ComboBox update. - Moves the construction of the MidiCCRack to the end, since we need the BB Editor to be created before the MIDI CC Rack to be able to connect this signal. --- include/TrackContainerView.h | 1 + src/gui/GuiApplication.cpp | 8 ++++---- src/gui/TrackContainerView.cpp | 2 ++ src/gui/widgets/MidiCCRackView.cpp | 7 +++++++ 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/include/TrackContainerView.h b/include/TrackContainerView.h index 6e952189b01..4597fe17240 100644 --- a/include/TrackContainerView.h +++ b/include/TrackContainerView.h @@ -183,6 +183,7 @@ public slots: signals: void positionChanged( const MidiTime & _pos ); + void movedTrackView(); } ; diff --git a/src/gui/GuiApplication.cpp b/src/gui/GuiApplication.cpp index 54ccef52d7b..988fdac2374 100644 --- a/src/gui/GuiApplication.cpp +++ b/src/gui/GuiApplication.cpp @@ -136,10 +136,6 @@ GuiApplication::GuiApplication() m_controllerRackView = new ControllerRackView; connect(m_controllerRackView, SIGNAL(destroyed(QObject*)), this, SLOT(childDestroyed(QObject*))); - displayInitProgress(tr("Preparing midi cc rack")); - m_midiCCRackView = new MidiCCRackView; - connect(m_midiCCRackView, SIGNAL(destroyed(QObject*)), this, SLOT(childDestroyed(QObject*))); - displayInitProgress(tr("Preparing project notes")); m_projectNotes = new ProjectNotes; connect(m_projectNotes, SIGNAL(destroyed(QObject*)), this, SLOT(childDestroyed(QObject*))); @@ -156,6 +152,10 @@ GuiApplication::GuiApplication() m_automationEditor = new AutomationEditorWindow; connect(m_automationEditor, SIGNAL(destroyed(QObject*)), this, SLOT(childDestroyed(QObject*))); + displayInitProgress(tr("Preparing midi cc rack")); + m_midiCCRackView = new MidiCCRackView; + connect(m_midiCCRackView, SIGNAL(destroyed(QObject*)), this, SLOT(childDestroyed(QObject*))); + splashScreen.finish(m_mainWindow); m_mainWindow->finalize(); diff --git a/src/gui/TrackContainerView.cpp b/src/gui/TrackContainerView.cpp index 9b51c76f272..0d955b3443f 100644 --- a/src/gui/TrackContainerView.cpp +++ b/src/gui/TrackContainerView.cpp @@ -175,6 +175,8 @@ void TrackContainerView::moveTrackView( TrackView * trackView, int indexTo ) m_trackViews.move( indexFrom, indexTo ); realignTracks(); + + emit movedTrackView(); } diff --git a/src/gui/widgets/MidiCCRackView.cpp b/src/gui/widgets/MidiCCRackView.cpp index 11bc142f9b2..601b33bed89 100644 --- a/src/gui/widgets/MidiCCRackView.cpp +++ b/src/gui/widgets/MidiCCRackView.cpp @@ -20,6 +20,8 @@ #include "BBTrackContainer.h" #include "Engine.h" #include "Song.h" +#include "SongEditor.h" +#include "BBEditor.h" MidiCCRackView::MidiCCRackView() : @@ -103,6 +105,11 @@ MidiCCRackView::MidiCCRackView() : this, SLOT( updateTracksComboBox() ) ); connect( Engine::getBBTrackContainer() , SIGNAL( trackRenamed() ), this, SLOT( updateTracksComboBox() ) ); + // Also when tracks are moved on the song editor and BB editor + connect( gui->songEditor()->m_editor, SIGNAL( movedTrackView() ), + this, SLOT( updateTracksComboBox() ) ); + connect( gui->getBBEditor()->trackContainerView(), SIGNAL( movedTrackView() ), + this, SLOT( updateTracksComboBox() ) ); // Adding everything to the main layout From cfead27b2b95ce2635efd02ea58bed6d0b7ac46c Mon Sep 17 00:00:00 2001 From: IanCaio Date: Mon, 13 Jul 2020 16:26:06 -0300 Subject: [PATCH 07/40] Starts implementing the CC controllers models Starts the implementation of the models that will hold the CC controller values for each Instrument Track. Selecting a different track now will show the values of the models for that particular track on the knobs. Observation: Read the "TODO" comment. There's line that keeps a SEGFAULT from happening, but the root cause has to be understood (maybe it's not a bug but still worth investigating the reasons behind it). --- include/InstrumentTrack.h | 3 +++ include/MidiCCRackView.h | 5 +++++ src/gui/widgets/MidiCCRackView.cpp | 36 +++++++++++++++++++++++++++--- src/tracks/InstrumentTrack.cpp | 7 ++++++ 4 files changed, 48 insertions(+), 3 deletions(-) diff --git a/include/InstrumentTrack.h b/include/InstrumentTrack.h index 29348b98eb6..78b3bbde17b 100644 --- a/include/InstrumentTrack.h +++ b/include/InstrumentTrack.h @@ -38,6 +38,7 @@ #include "Pitch.h" #include "Plugin.h" #include "Track.h" +#include "MidiCCRackView.h" @@ -221,6 +222,8 @@ class LMMS_EXPORT InstrumentTrack : public Track, public MidiEventProcessor void autoAssignMidiDevice( bool ); + FloatModel *m_midiCCModel[MIDI_CC_MAX_CONTROLLERS]; + signals: void instrumentChanged(); void midiNoteOn( const Note& ); diff --git a/include/MidiCCRackView.h b/include/MidiCCRackView.h index 631663bc7de..6e10ed315f4 100644 --- a/include/MidiCCRackView.h +++ b/include/MidiCCRackView.h @@ -9,9 +9,12 @@ #include "ComboBox.h" #include "ComboBoxModel.h" #include "Knob.h" +#include "TrackContainer.h" const int MIDI_CC_MAX_CONTROLLERS = 127; +class InstrumentTrack; + class MidiCCRackView : public QWidget, public SerializingObject { Q_OBJECT @@ -29,10 +32,12 @@ class MidiCCRackView : public QWidget, public SerializingObject public slots: void updateTracksComboBox(); + void updateKnobsModels(); private: ComboBox *m_trackComboBox; ComboBoxModel *m_trackComboBoxModel; + TrackContainer::TrackList m_tracks; // List with pointers to the ComboBox tracks themselfs Knob *m_controllerKnob[MIDI_CC_MAX_CONTROLLERS]; // Holds the knob widgets for each controller diff --git a/src/gui/widgets/MidiCCRackView.cpp b/src/gui/widgets/MidiCCRackView.cpp index 601b33bed89..e9eb0c7611b 100644 --- a/src/gui/widgets/MidiCCRackView.cpp +++ b/src/gui/widgets/MidiCCRackView.cpp @@ -16,6 +16,7 @@ #include "GroupBox.h" #include "Knob.h" #include "Track.h" +#include "InstrumentTrack.h" #include "TrackContainer.h" #include "BBTrackContainer.h" #include "Engine.h" @@ -111,6 +112,9 @@ MidiCCRackView::MidiCCRackView() : connect( gui->getBBEditor()->trackContainerView(), SIGNAL( movedTrackView() ), this, SLOT( updateTracksComboBox() ) ); + // Connection to update the knobs when the ComboBox selects another track + connect( m_trackComboBoxModel, SIGNAL( dataChanged() ), + this, SLOT( updateKnobsModels() )); // Adding everything to the main layout mainLayout->addWidget(trackToolBar); @@ -123,15 +127,18 @@ MidiCCRackView::~MidiCCRackView() void MidiCCRackView::updateTracksComboBox() { - // Reset the combo box model and fill it with instrument tracks from the song editor + // Reset the combo box model to fill it with instrument tracks from the song/BB editors m_trackComboBoxModel->clear(); + // Reset our list with pointers to the tracks + m_tracks.clear(); + TrackContainer::TrackList songEditorTracks; - songEditorTracks += Engine::getSong()->tracks(); + songEditorTracks = Engine::getSong()->tracks(); int songEditorID = 1; TrackContainer::TrackList bbEditorTracks; - bbEditorTracks += Engine::getBBTrackContainer()->tracks(); + bbEditorTracks = Engine::getBBTrackContainer()->tracks(); int bbEditorID = 1; for(Track *t: songEditorTracks) @@ -139,6 +146,7 @@ void MidiCCRackView::updateTracksComboBox() if( t->type() == Track::InstrumentTrack ) { m_trackComboBoxModel->addItem("SongEditor: " + QString::number(songEditorID) + ". " + t->name()); + m_tracks += t; ++songEditorID; } } @@ -147,9 +155,31 @@ void MidiCCRackView::updateTracksComboBox() if( t->type() == Track::InstrumentTrack ) { m_trackComboBoxModel->addItem("BBEditor: " + QString::number(bbEditorID) + ". " + t->name()); + m_tracks += t; ++bbEditorID; } } + + updateKnobsModels(); +} + +void MidiCCRackView::updateKnobsModels() +{ + if( m_tracks.size() > 0 ) + { + InstrumentTrack *selectedTrack = dynamic_cast( m_tracks[ m_trackComboBoxModel->value() ] ); + + // TODO: I need to figure out why this line is necessary. Without it I get a segfault because at + // LMMS's startup sometimes m_tracks will hold tracks that have type() == Tracks::InstrumentTracks + // but casting the to InstrumentTrack * returns a nullptr. Meaning maybe the constructor wasn't + // executed yet. + if( selectedTrack ) + { + for( int i = 0; i < MIDI_CC_MAX_CONTROLLERS; ++i ){ + m_controllerKnob[i]->setModel( selectedTrack->m_midiCCModel[i] ); + } + } + } } void MidiCCRackView::saveSettings( QDomDocument & _doc, diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index 855902fe961..cbb86949e39 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -74,6 +74,7 @@ #include "StringPairDrag.h" #include "TrackContainerView.h" #include "TrackLabelButton.h" +#include "MidiCCRackView.h" const char * volume_help = QT_TRANSLATE_NOOP( "InstrumentTrack", @@ -125,6 +126,12 @@ InstrumentTrack::InstrumentTrack( TrackContainer* tc ) : m_runningMidiNotes[i] = 0; } + // Initialize the MIDI CC controller models + for( int i = 0; i < MIDI_CC_MAX_CONTROLLERS; ++i ) + { + m_midiCCModel[i] = new FloatModel(0.0f, 0.0f, 127.0f, 1.0f); + } + setName( tr( "Default preset" ) ); From f73d42f51190f6f8c97235590c8a02924efefbbb Mon Sep 17 00:00:00 2001 From: IanCaio Date: Mon, 13 Jul 2020 21:58:55 -0300 Subject: [PATCH 08/40] Implements the CC event handling itself This commit implements the MIDI CC event handling feature itself. Changing the values on the CC controller knobs inside the MIDI CC Rack now results in MIDI CC event messages being triggered on the selected track. Those can also be automated so those messages are generated during the song play. Some small fixes were also made. Summary of changes: - Changes the number of CC controllers to 128 and fix the numbering so they are counted from 0-127. - Adds a name to the FloatModels of the CC controllers so they are more easily identified in the automation tracks. - Adds a SLOT method to the InstrumentTrack class that will receive a controller number as an argument and process a MIDI CC Event with the value of this controller to the output channel of the track. - Connects the dataChanged signal of every controller FloatModel so they trigger this processing method everytime the value is changed. Maps all the knobs models to the appropriate method call using a QSignalMapper. --- include/InstrumentTrack.h | 2 ++ include/MidiCCRackView.h | 2 +- src/gui/widgets/MidiCCRackView.cpp | 2 +- src/tracks/InstrumentTrack.cpp | 25 +++++++++++++++++++++++-- 4 files changed, 27 insertions(+), 4 deletions(-) diff --git a/include/InstrumentTrack.h b/include/InstrumentTrack.h index 78b3bbde17b..c0b6eb6bc35 100644 --- a/include/InstrumentTrack.h +++ b/include/InstrumentTrack.h @@ -232,6 +232,8 @@ class LMMS_EXPORT InstrumentTrack : public Track, public MidiEventProcessor void newNote(); void endNote(); +public slots: + void processCCEvent(int controller); protected: QString nodeName() const override diff --git a/include/MidiCCRackView.h b/include/MidiCCRackView.h index 6e10ed315f4..329553243fa 100644 --- a/include/MidiCCRackView.h +++ b/include/MidiCCRackView.h @@ -11,7 +11,7 @@ #include "Knob.h" #include "TrackContainer.h" -const int MIDI_CC_MAX_CONTROLLERS = 127; +const int MIDI_CC_MAX_CONTROLLERS = 128; class InstrumentTrack; diff --git a/src/gui/widgets/MidiCCRackView.cpp b/src/gui/widgets/MidiCCRackView.cpp index e9eb0c7611b..bf19ea509a4 100644 --- a/src/gui/widgets/MidiCCRackView.cpp +++ b/src/gui/widgets/MidiCCRackView.cpp @@ -86,7 +86,7 @@ MidiCCRackView::MidiCCRackView() : // Adds the controller knobs for(int i = 0; i < MIDI_CC_MAX_CONTROLLERS; i++){ m_controllerKnob[i] = new Knob( knobBright_26 ); - m_controllerKnob[i]->setLabel( QString("CC %1").arg(QString::number(i + 1)) ); + m_controllerKnob[i]->setLabel( QString("CC %1").arg(QString::number(i)) ); knobsAreaLayout->addWidget( m_controllerKnob[i], i/3, i%3 ); } diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index cbb86949e39..d9b36ef44c2 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include "FileDialog.h" #include "InstrumentTrack.h" @@ -126,11 +127,19 @@ InstrumentTrack::InstrumentTrack( TrackContainer* tc ) : m_runningMidiNotes[i] = 0; } - // Initialize the MIDI CC controller models + // Initialize the MIDI CC controller models and connect them to the method that processes + // the midi cc events + QSignalMapper *midiCCSignalMapper = new QSignalMapper( this ); + for( int i = 0; i < MIDI_CC_MAX_CONTROLLERS; ++i ) { - m_midiCCModel[i] = new FloatModel(0.0f, 0.0f, 127.0f, 1.0f); + m_midiCCModel[i] = new FloatModel(0.0f, 0.0f, 127.0f, 1.0f, NULL, QString("CC Controller ") + QString::number(i)); + connect( m_midiCCModel[i], SIGNAL( dataChanged() ), + midiCCSignalMapper, SLOT( map() ) ); + midiCCSignalMapper->setMapping( m_midiCCModel[i], i ); } + connect( midiCCSignalMapper, SIGNAL( mapped(int) ), + this, SLOT( processCCEvent(int) ) ); setName( tr( "Default preset" ) ); @@ -256,6 +265,18 @@ MidiEvent InstrumentTrack::applyMasterKey( const MidiEvent& event ) +void InstrumentTrack::processCCEvent(int controller) +{ + uint8_t channel = static_cast( midiPort()->realOutputChannel() ); + uint16_t cc = static_cast( controller ); + uint16_t value = static_cast( m_midiCCModel[ controller ]->value() ); + + processOutEvent( MidiEvent( MidiControlChange, channel, cc, value ) ); +} + + + + void InstrumentTrack::processInEvent( const MidiEvent& event, const MidiTime& time, f_cnt_t offset ) { if( Engine::getSong()->isExporting() ) From 72addfe0143d9fa5807899efe26a7ae2dca0d35c Mon Sep 17 00:00:00 2001 From: IanCaio Date: Mon, 13 Jul 2020 23:35:29 -0300 Subject: [PATCH 09/40] Adds the enable/disable functionality for MIDI CC Now the GroupBox LED button will enable or disable the MIDI CC events triggering for the selected InstrumentTrack. The LED button is connected to the selected InstrumentTrack's BoolModel. If it's disabled, the callback function that processes the MIDI CC messages will be called but will return before processing the MIDI CC event. The connection isn't destroyed in that case (probably the overhead of having to recreate the connection every time we enable the MIDI CC for the track doesn't compensate the unnecessary function call). When the LED button is enabled, the MIDI CC event is processed normally. One behavior that needs to be made clear is the following: If a value is selected while MIDI CC is enabled (i.e.: 120), then it's disabled, and another value is selected while it's disabled (i.e.: 40), when the MIDI CC is enabled again an event WON'T be triggered until a change in the value is made AFTER it was enabled again. That sounds reasonable and what would be expected from a hardware MIDI controller (when a controller is turned on with a knob on a value, it will only trigger an event for that knob when it's moved to a different value). So I believe it should be kept that way. --- include/InstrumentTrack.h | 1 + include/MidiCCRackView.h | 2 ++ src/gui/widgets/MidiCCRackView.cpp | 6 ++++++ src/tracks/InstrumentTrack.cpp | 11 +++++++++++ 4 files changed, 20 insertions(+) diff --git a/include/InstrumentTrack.h b/include/InstrumentTrack.h index c0b6eb6bc35..25a39709e84 100644 --- a/include/InstrumentTrack.h +++ b/include/InstrumentTrack.h @@ -222,6 +222,7 @@ class LMMS_EXPORT InstrumentTrack : public Track, public MidiEventProcessor void autoAssignMidiDevice( bool ); + BoolModel *m_midiCCEnable; FloatModel *m_midiCCModel[MIDI_CC_MAX_CONTROLLERS]; signals: diff --git a/include/MidiCCRackView.h b/include/MidiCCRackView.h index 329553243fa..7b050e480c0 100644 --- a/include/MidiCCRackView.h +++ b/include/MidiCCRackView.h @@ -39,6 +39,8 @@ public slots: ComboBoxModel *m_trackComboBoxModel; TrackContainer::TrackList m_tracks; // List with pointers to the ComboBox tracks themselfs + PixmapButton *m_midiCCLed; // LED to enable disable MIDI CC + Knob *m_controllerKnob[MIDI_CC_MAX_CONTROLLERS]; // Holds the knob widgets for each controller //protected: diff --git a/src/gui/widgets/MidiCCRackView.cpp b/src/gui/widgets/MidiCCRackView.cpp index bf19ea509a4..251cfac0d07 100644 --- a/src/gui/widgets/MidiCCRackView.cpp +++ b/src/gui/widgets/MidiCCRackView.cpp @@ -66,6 +66,8 @@ MidiCCRackView::MidiCCRackView() : // Knobs GroupBox - Here we have the MIDI CC controller knobs for the selected track GroupBox *knobsGroupBox = new GroupBox( tr("MIDI CC Knobs:") ); + m_midiCCLed = knobsGroupBox->ledButton(); + // Layout to keep scrollable area under the GroupBox header QVBoxLayout *knobsGroupBoxLayout = new QVBoxLayout(); knobsGroupBoxLayout->setContentsMargins( 5, 16, 5, 5 ); @@ -175,6 +177,10 @@ void MidiCCRackView::updateKnobsModels() // executed yet. if( selectedTrack ) { + // Set the LED button to enable/disable the track midi cc + m_midiCCLed->setModel( selectedTrack->m_midiCCEnable ); + + // Set the model for each Knob for( int i = 0; i < MIDI_CC_MAX_CONTROLLERS; ++i ){ m_controllerKnob[i]->setModel( selectedTrack->m_midiCCModel[i] ); } diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index d9b36ef44c2..2c0d737f073 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -127,6 +127,11 @@ InstrumentTrack::InstrumentTrack( TrackContainer* tc ) : m_runningMidiNotes[i] = 0; } + + // Initialize the m_midiCCEnabled variable, but it's actually going to be connected + // to a LedButton + m_midiCCEnable = new BoolModel( false, NULL, "Enable/Disable MIDI CC" ); + // Initialize the MIDI CC controller models and connect them to the method that processes // the midi cc events QSignalMapper *midiCCSignalMapper = new QSignalMapper( this ); @@ -267,6 +272,12 @@ MidiEvent InstrumentTrack::applyMasterKey( const MidiEvent& event ) void InstrumentTrack::processCCEvent(int controller) { + // Does nothing if the LED is disabled + if( !m_midiCCEnable->value() ) + { + return; + } + uint8_t channel = static_cast( midiPort()->realOutputChannel() ); uint16_t cc = static_cast( controller ); uint16_t value = static_cast( m_midiCCModel[ controller ]->value() ); From 65a2bc0f0ff5265214aa9bd01e1ecd7743af0eea Mon Sep 17 00:00:00 2001 From: IanCaio Date: Tue, 14 Jul 2020 07:51:22 -0300 Subject: [PATCH 10/40] Changes shortcuts and titles There was a recent change on master that assigned different shortcuts to the editors. Instead of using F1-F12 those now use Ctrl + 1-7. I assigned CTRL + 8 to the MIDI CC rack for consistency. Also, some titles were corrected in terms of letter case ("midi" -> "MIDI" and "cc" -> "CC"). --- src/gui/GuiApplication.cpp | 2 +- src/gui/MainWindow.cpp | 4 ++-- src/gui/widgets/MidiCCRackView.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/gui/GuiApplication.cpp b/src/gui/GuiApplication.cpp index 988fdac2374..50f8595eb51 100644 --- a/src/gui/GuiApplication.cpp +++ b/src/gui/GuiApplication.cpp @@ -152,7 +152,7 @@ GuiApplication::GuiApplication() m_automationEditor = new AutomationEditorWindow; connect(m_automationEditor, SIGNAL(destroyed(QObject*)), this, SLOT(childDestroyed(QObject*))); - displayInitProgress(tr("Preparing midi cc rack")); + displayInitProgress(tr("Preparing MIDI CC rack")); m_midiCCRackView = new MidiCCRackView; connect(m_midiCCRackView, SIGNAL(destroyed(QObject*)), this, SLOT(childDestroyed(QObject*))); diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index bce213b9ebb..93c6770f597 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -540,11 +540,11 @@ void MainWindow::finalize() ToolButton * midi_cc_rack_window = new ToolButton( embed::getIconPixmap( "midi_cc_rack" ), - tr( "Show/hide midi cc rack") + + tr( "Show/hide MIDI CC rack") + " (F12)", this, SLOT( toggleMidiCCRack() ), m_toolBar ); - midi_cc_rack_window->setShortcut( Qt::Key_F12 ); + midi_cc_rack_window->setShortcut( Qt::CTRL + Qt::Key_8 ); m_toolBarLayout->addWidget( song_editor_window, 1, 1 ); m_toolBarLayout->addWidget( bb_editor_window, 1, 2 ); diff --git a/src/gui/widgets/MidiCCRackView.cpp b/src/gui/widgets/MidiCCRackView.cpp index 251cfac0d07..fe9bf871e69 100644 --- a/src/gui/widgets/MidiCCRackView.cpp +++ b/src/gui/widgets/MidiCCRackView.cpp @@ -29,7 +29,7 @@ MidiCCRackView::MidiCCRackView() : QWidget() { setWindowIcon( embed::getIconPixmap( "midi_cc_rack" ) ); - setWindowTitle( tr("Midi CC Rack") ); + setWindowTitle( tr("MIDI CC Rack") ); QMdiSubWindow * subWin = gui->mainWindow()->addWindowedWidget( this ); From f2d5302b115660c369ca896bd968193676586906 Mon Sep 17 00:00:00 2001 From: IanCaio Date: Tue, 14 Jul 2020 08:38:26 -0300 Subject: [PATCH 11/40] Removes unused comment --- include/MidiCCRackView.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/include/MidiCCRackView.h b/include/MidiCCRackView.h index 7b050e480c0..8feff14ff25 100644 --- a/include/MidiCCRackView.h +++ b/include/MidiCCRackView.h @@ -43,9 +43,6 @@ public slots: Knob *m_controllerKnob[MIDI_CC_MAX_CONTROLLERS]; // Holds the knob widgets for each controller -//protected: -// void closeEvent( QCloseEvent * _ce ) override; - }; #endif From 15141a90506bdcb270f99cdeca64578a495b2d4c Mon Sep 17 00:00:00 2001 From: IanCaio Date: Tue, 14 Jul 2020 10:46:49 -0300 Subject: [PATCH 12/40] Fix SEGFAULT bug and hide MIDI CC rack at start up A Segfault error was being caused when clicking on the GroupBox label, because instead of setting the model in the GroupBox widget I was setting the model on the LED button widget. The appropriate changes were made to fix the issue. Also, the MIDI CC rack window is now hidden at start up by default. --- include/MidiCCRackView.h | 3 ++- src/gui/widgets/MidiCCRackView.cpp | 11 +++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/include/MidiCCRackView.h b/include/MidiCCRackView.h index 8feff14ff25..086ebf08241 100644 --- a/include/MidiCCRackView.h +++ b/include/MidiCCRackView.h @@ -10,6 +10,7 @@ #include "ComboBoxModel.h" #include "Knob.h" #include "TrackContainer.h" +#include "GroupBox.h" const int MIDI_CC_MAX_CONTROLLERS = 128; @@ -39,7 +40,7 @@ public slots: ComboBoxModel *m_trackComboBoxModel; TrackContainer::TrackList m_tracks; // List with pointers to the ComboBox tracks themselfs - PixmapButton *m_midiCCLed; // LED to enable disable MIDI CC + GroupBox *m_midiCCGroupBox; // MIDI CC GroupBox (used to enable disable MIDI CC) Knob *m_controllerKnob[MIDI_CC_MAX_CONTROLLERS]; // Holds the knob widgets for each controller diff --git a/src/gui/widgets/MidiCCRackView.cpp b/src/gui/widgets/MidiCCRackView.cpp index fe9bf871e69..cacd5cefb73 100644 --- a/src/gui/widgets/MidiCCRackView.cpp +++ b/src/gui/widgets/MidiCCRackView.cpp @@ -44,6 +44,7 @@ MidiCCRackView::MidiCCRackView() : subWin->resize( 350, 300 ); subWin->setFixedWidth( 350 ); subWin->setMinimumHeight( 300 ); + subWin->hide(); // Main window layout QVBoxLayout *mainLayout = new QVBoxLayout( this ); @@ -64,15 +65,13 @@ MidiCCRackView::MidiCCRackView() : trackToolBar->setFixedHeight(40); // Knobs GroupBox - Here we have the MIDI CC controller knobs for the selected track - GroupBox *knobsGroupBox = new GroupBox( tr("MIDI CC Knobs:") ); - - m_midiCCLed = knobsGroupBox->ledButton(); + m_midiCCGroupBox = new GroupBox( tr("MIDI CC Knobs:") ); // Layout to keep scrollable area under the GroupBox header QVBoxLayout *knobsGroupBoxLayout = new QVBoxLayout(); knobsGroupBoxLayout->setContentsMargins( 5, 16, 5, 5 ); - knobsGroupBox->setLayout(knobsGroupBoxLayout); + m_midiCCGroupBox->setLayout(knobsGroupBoxLayout); // Scrollable area + widget + its layout that will have all the knobs QScrollArea *knobsScrollArea = new QScrollArea(); @@ -120,7 +119,7 @@ MidiCCRackView::MidiCCRackView() : // Adding everything to the main layout mainLayout->addWidget(trackToolBar); - mainLayout->addWidget(knobsGroupBox); + mainLayout->addWidget(m_midiCCGroupBox); } MidiCCRackView::~MidiCCRackView() @@ -178,7 +177,7 @@ void MidiCCRackView::updateKnobsModels() if( selectedTrack ) { // Set the LED button to enable/disable the track midi cc - m_midiCCLed->setModel( selectedTrack->m_midiCCEnable ); + m_midiCCGroupBox->setModel( selectedTrack->m_midiCCEnable ); // Set the model for each Knob for( int i = 0; i < MIDI_CC_MAX_CONTROLLERS; ++i ){ From 6dc70181f5073e0603f6a84b1367229ee6701308 Mon Sep 17 00:00:00 2001 From: IanCaio Date: Tue, 14 Jul 2020 22:45:37 -0300 Subject: [PATCH 13/40] Save/Load MIDI controllers models on project file With this commit, the models related to MIDI CC are saved in the Instrument Track DOM structure. The models are m_midiCCEnable and m_midiCCModel (for each controller). m_midiCCEnable is saved as an attribute on called "enablecc" and m_midiCCModel is saved in a child element called . This allows the user to save projects with CC automation tracks. TODO: - Check if changes on the DataFile class are necessary to make older projects compatible. --- src/tracks/InstrumentTrack.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index 2c0d737f073..09c29e192cd 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -795,6 +795,15 @@ void InstrumentTrack::saveTrackSpecificSettings( QDomDocument& doc, QDomElement m_baseNoteModel.saveSettings( doc, thisElement, "basenote" ); m_useMasterPitchModel.saveSettings( doc, thisElement, "usemasterpitch"); + // Save MIDI CC stuff + m_midiCCEnable->saveSettings( doc, thisElement, "enablecc" ); + QDomElement midiCC = doc.createElement( "midicontrollers" ); + thisElement.appendChild( midiCC ); + for( int i = 0; i < MIDI_CC_MAX_CONTROLLERS; ++i ) + { + m_midiCCModel[i]->saveSettings( doc, midiCC, "cc" + QString::number(i) ); + } + if( m_instrument != NULL ) { QDomElement i = doc.createElement( "instrument" ); @@ -850,6 +859,9 @@ void InstrumentTrack::loadTrackSpecificSettings( const QDomElement & thisElement m_baseNoteModel.loadSettings( thisElement, "basenote" ); m_useMasterPitchModel.loadSettings( thisElement, "usemasterpitch"); + // Load MIDI CC stuff + m_midiCCEnable->loadSettings( thisElement, "enablecc" ); + // clear effect-chain just in case we load an old preset without FX-data m_audioPort.effects()->clear(); @@ -897,6 +909,13 @@ void InstrumentTrack::loadTrackSpecificSettings( const QDomElement & thisElement emit instrumentChanged(); } } + else if(node.nodeName() == "midicontrollers") + { + for( int i = 0; i < MIDI_CC_MAX_CONTROLLERS; ++i ) + { + m_midiCCModel[i]->loadSettings( node.toElement(), "cc" + QString::number(i) ); + } + } // 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 From cedcf6b45905093e8bd6f53b63904917b10625f8 Mon Sep 17 00:00:00 2001 From: IanCaio Date: Wed, 15 Jul 2020 00:10:33 -0300 Subject: [PATCH 14/40] Uses lambda functions instead of QSignalMapper When connecting the MIDI CC models to the InstrumentTrack::processCCEvent method I was using QSignalMapper to call the method with the appropriate parameter. Now lambda functions are used instead, which saves lines and makes it more readable. --- src/tracks/InstrumentTrack.cpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index 09c29e192cd..6ac17f8074d 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -134,18 +134,12 @@ InstrumentTrack::InstrumentTrack( TrackContainer* tc ) : // Initialize the MIDI CC controller models and connect them to the method that processes // the midi cc events - QSignalMapper *midiCCSignalMapper = new QSignalMapper( this ); - for( int i = 0; i < MIDI_CC_MAX_CONTROLLERS; ++i ) { m_midiCCModel[i] = new FloatModel(0.0f, 0.0f, 127.0f, 1.0f, NULL, QString("CC Controller ") + QString::number(i)); - connect( m_midiCCModel[i], SIGNAL( dataChanged() ), - midiCCSignalMapper, SLOT( map() ) ); - midiCCSignalMapper->setMapping( m_midiCCModel[i], i ); + connect( m_midiCCModel[i], &FloatModel::dataChanged, + this, [this, i]{ processCCEvent(i); }, Qt::DirectConnection ); } - connect( midiCCSignalMapper, SIGNAL( mapped(int) ), - this, SLOT( processCCEvent(int) ) ); - setName( tr( "Default preset" ) ); From 0ff28359fd4bbc932261cda1681bec12118fac1d Mon Sep 17 00:00:00 2001 From: IanCaio Date: Wed, 15 Jul 2020 00:22:32 -0300 Subject: [PATCH 15/40] Corrects tooltip of MIDI CC rack I had changed the MIDI CC rack shortcut from F12 to Ctrl+8 on an earlier commit, but forgot to update the ToolTip. --- src/gui/MainWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index 93c6770f597..087d1771bce 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -541,7 +541,7 @@ void MainWindow::finalize() ToolButton * midi_cc_rack_window = new ToolButton( embed::getIconPixmap( "midi_cc_rack" ), tr( "Show/hide MIDI CC rack") + - " (F12)", + " (Ctrl+8)", this, SLOT( toggleMidiCCRack() ), m_toolBar ); midi_cc_rack_window->setShortcut( Qt::CTRL + Qt::Key_8 ); From 64c83ff8c26dca8d6e52589b3b975b9e4770a4a8 Mon Sep 17 00:00:00 2001 From: IanCaio Date: Wed, 15 Jul 2020 01:13:40 -0300 Subject: [PATCH 16/40] Removes unused header After replacing QSignalMapper for lambda functions on a previous commit I forgot to remove the header. --- src/tracks/InstrumentTrack.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index 6ac17f8074d..14df2640b98 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -35,7 +35,6 @@ #include #include #include -#include #include "FileDialog.h" #include "InstrumentTrack.h" From 36a6de36ab4f5e870e92923ffda274f15506f63e Mon Sep 17 00:00:00 2001 From: IanCaio Date: Fri, 17 Jul 2020 21:24:50 -0300 Subject: [PATCH 17/40] Includes the MIDI CC Rack in the View Menu I forgot to add an action in the View Menu for accessing the MIDI CC Rack. This commit adds it. --- src/gui/MainWindow.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index 087d1771bce..930c2904a1a 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -1148,6 +1148,10 @@ void MainWindow::updateViewMenu() tr( "Project Notes" ) + "\tCtrl+7", this, SLOT( toggleProjectNotesWin() ) ); + m_viewMenu->addAction(embed::getIconPixmap( "midi_cc_rack" ), + tr( "MIDI CC Rack" ) + "\tCtrl+8", + this, SLOT( toggleMidiCCRack() ) + ); m_viewMenu->addSeparator(); From c40fc49caf0adecf7ee6c484e2c5d9121cd52cd1 Mon Sep 17 00:00:00 2001 From: IanCaio Date: Sun, 2 Aug 2020 21:34:33 -0300 Subject: [PATCH 18/40] Replaces constant with existent one from Midi.h Instead of declaring a duplicate constant in MidiCCRackView.h we now use a constant that was already declared on Midi.h for the total number of MIDI controllers. Added copyright message to the beginning of src/gui/widgets/MidiCCRackView.cpp. Removed #include on src/gui/widgets/MidiCCRackView.cpp. Added a TODO comment over the call to processOutEvent, since it will have to be decided whether to use processInEvent or processOutEvent. Both would work, but they would correspond to two different situations and would have slightly different behavior. One would act like the MIDI CC rack was completely external (almost equivalent to a hardware MIDI controller) and the other would act like the MIDI CC rack was part of the instrument track (being the one generating the events). --- include/InstrumentTrack.h | 4 ++-- include/MidiCCRackView.h | 5 ++--- src/gui/widgets/MidiCCRackView.cpp | 30 +++++++++++++++++++++++++++--- src/tracks/InstrumentTrack.cpp | 16 +++++++++++++--- 4 files changed, 44 insertions(+), 11 deletions(-) diff --git a/include/InstrumentTrack.h b/include/InstrumentTrack.h index 25a39709e84..96a8d4299fa 100644 --- a/include/InstrumentTrack.h +++ b/include/InstrumentTrack.h @@ -38,7 +38,7 @@ #include "Pitch.h" #include "Plugin.h" #include "Track.h" -#include "MidiCCRackView.h" +#include "Midi.h" @@ -223,7 +223,7 @@ class LMMS_EXPORT InstrumentTrack : public Track, public MidiEventProcessor void autoAssignMidiDevice( bool ); BoolModel *m_midiCCEnable; - FloatModel *m_midiCCModel[MIDI_CC_MAX_CONTROLLERS]; + FloatModel *m_midiCCModel[MidiControllerCount]; signals: void instrumentChanged(); diff --git a/include/MidiCCRackView.h b/include/MidiCCRackView.h index 086ebf08241..03cb1d8d068 100644 --- a/include/MidiCCRackView.h +++ b/include/MidiCCRackView.h @@ -11,8 +11,7 @@ #include "Knob.h" #include "TrackContainer.h" #include "GroupBox.h" - -const int MIDI_CC_MAX_CONTROLLERS = 128; +#include "Midi.h" class InstrumentTrack; @@ -42,7 +41,7 @@ public slots: GroupBox *m_midiCCGroupBox; // MIDI CC GroupBox (used to enable disable MIDI CC) - Knob *m_controllerKnob[MIDI_CC_MAX_CONTROLLERS]; // Holds the knob widgets for each controller + Knob *m_controllerKnob[MidiControllerCount]; // Holds the knob widgets for each controller }; diff --git a/src/gui/widgets/MidiCCRackView.cpp b/src/gui/widgets/MidiCCRackView.cpp index cacd5cefb73..19d691b3acd 100644 --- a/src/gui/widgets/MidiCCRackView.cpp +++ b/src/gui/widgets/MidiCCRackView.cpp @@ -1,4 +1,28 @@ -#include // For Qt::WindowFlags +/* + * MidiCCRackView.cpp - implementation of the MIDI CC rack widget + * + * Copyright (c) 2020 Ian Caio + * + * This file is part of LMMS - https://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. + * + */ + + #include #include #include @@ -85,7 +109,7 @@ MidiCCRackView::MidiCCRackView() : knobsGroupBoxLayout->addWidget(knobsScrollArea); // Adds the controller knobs - for(int i = 0; i < MIDI_CC_MAX_CONTROLLERS; i++){ + for(int i = 0; i < MidiControllerCount; i++){ m_controllerKnob[i] = new Knob( knobBright_26 ); m_controllerKnob[i]->setLabel( QString("CC %1").arg(QString::number(i)) ); knobsAreaLayout->addWidget( m_controllerKnob[i], i/3, i%3 ); @@ -180,7 +204,7 @@ void MidiCCRackView::updateKnobsModels() m_midiCCGroupBox->setModel( selectedTrack->m_midiCCEnable ); // Set the model for each Knob - for( int i = 0; i < MIDI_CC_MAX_CONTROLLERS; ++i ){ + for( int i = 0; i < MidiControllerCount; ++i ){ m_controllerKnob[i]->setModel( selectedTrack->m_midiCCModel[i] ); } } diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index 315bd12da22..4c5e06d1200 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -133,7 +133,7 @@ InstrumentTrack::InstrumentTrack( TrackContainer* tc ) : // Initialize the MIDI CC controller models and connect them to the method that processes // the midi cc events - for( int i = 0; i < MIDI_CC_MAX_CONTROLLERS; ++i ) + for( int i = 0; i < MidiControllerCount; ++i ) { m_midiCCModel[i] = new FloatModel(0.0f, 0.0f, 127.0f, 1.0f, NULL, QString("CC Controller ") + QString::number(i)); connect( m_midiCCModel[i], &FloatModel::dataChanged, @@ -275,6 +275,16 @@ void InstrumentTrack::processCCEvent(int controller) uint16_t cc = static_cast( controller ); uint16_t value = static_cast( m_midiCCModel[ controller ]->value() ); + // TODO: Decide whether we want MIDI CC rack control events to be interpreted as external (coming + // from a hardware controller) or internal (generated by the instrument track). If they are to be + // interpreted as external, processInEvent should be used instead. In this case the instrument track + // will behave EXACTLY as if a hardware MIDI controller sent the events to it, processing some of the + // events and forwarding the rest to the instrument plugin with handleMidiEvent. The events in this case + // are not further forwarded with MidiPorts. If we decide to interpret CC events as internal they won't + // be interpreted as CC events coming from hardware (the instrument track is not going to do any preliminar + // processing like for the Sustain CC message for example), but instead ALL CC events will be generated + // and further forwarded by processOutEvent to the instrument plugin and any other track that is connected + // through the MIDI ports to this one. Those are the ones that will do what they will with the event. processOutEvent( MidiEvent( MidiControlChange, channel, cc, value ) ); } @@ -792,7 +802,7 @@ void InstrumentTrack::saveTrackSpecificSettings( QDomDocument& doc, QDomElement m_midiCCEnable->saveSettings( doc, thisElement, "enablecc" ); QDomElement midiCC = doc.createElement( "midicontrollers" ); thisElement.appendChild( midiCC ); - for( int i = 0; i < MIDI_CC_MAX_CONTROLLERS; ++i ) + for( int i = 0; i < MidiControllerCount; ++i ) { m_midiCCModel[i]->saveSettings( doc, midiCC, "cc" + QString::number(i) ); } @@ -904,7 +914,7 @@ void InstrumentTrack::loadTrackSpecificSettings( const QDomElement & thisElement } else if(node.nodeName() == "midicontrollers") { - for( int i = 0; i < MIDI_CC_MAX_CONTROLLERS; ++i ) + for( int i = 0; i < MidiControllerCount; ++i ) { m_midiCCModel[i]->loadSettings( node.toElement(), "cc" + QString::number(i) ); } From e0a3939500d5f3f91b025a5059eb7fb7fd396407 Mon Sep 17 00:00:00 2001 From: IanCaio Date: Sun, 2 Aug 2020 23:46:29 -0300 Subject: [PATCH 19/40] Processes MIDI CC rack events as hardware ones Instead of using processOutEvent to process the MIDI CC events generated by the MIDI CC rack (which is analogous to having them being processed as they were generated by the instrument track) we now use processInEvent. That is similar to simulating a physical MIDI controller because the events will be processed exactly like they were received through the MIDI input ports of the instrument track from a controller. I decided for this design to avoid having 2 different behaviors: One for physical MIDI controllers and one for the MIDI CC rack. The only possible downside is that MIDI CC events can't be forwarded from one track to another, which is true for physical controller events as well, so it shouldn't be an issue (if in the future we allow forwarding those events we should allow it for both hardware controllers and MIDI CC rack, changing the processInEvent method). The closest we can get from mimicking the behavior of physical controllers the more predictable the feature will be for an user accustomed with the hardware controllers. Any changes to the way LMMS acts when receiving CC events should affect both hardware and MIDI CC rack controllers. --- src/tracks/InstrumentTrack.cpp | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index 4c5e06d1200..97e6cfa4762 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -275,17 +275,8 @@ void InstrumentTrack::processCCEvent(int controller) uint16_t cc = static_cast( controller ); uint16_t value = static_cast( m_midiCCModel[ controller ]->value() ); - // TODO: Decide whether we want MIDI CC rack control events to be interpreted as external (coming - // from a hardware controller) or internal (generated by the instrument track). If they are to be - // interpreted as external, processInEvent should be used instead. In this case the instrument track - // will behave EXACTLY as if a hardware MIDI controller sent the events to it, processing some of the - // events and forwarding the rest to the instrument plugin with handleMidiEvent. The events in this case - // are not further forwarded with MidiPorts. If we decide to interpret CC events as internal they won't - // be interpreted as CC events coming from hardware (the instrument track is not going to do any preliminar - // processing like for the Sustain CC message for example), but instead ALL CC events will be generated - // and further forwarded by processOutEvent to the instrument plugin and any other track that is connected - // through the MIDI ports to this one. Those are the ones that will do what they will with the event. - processOutEvent( MidiEvent( MidiControlChange, channel, cc, value ) ); + // Process the MIDI CC event as if it was generated by a physical MIDI controller + processInEvent( MidiEvent( MidiControlChange, channel, cc, value ) ); } From 6abd13062a50d49a247dbfaf4baa6bed4d123eba Mon Sep 17 00:00:00 2001 From: IanCaio Date: Wed, 9 Sep 2020 13:25:28 -0300 Subject: [PATCH 20/40] Fixes a Segmentation Fault bug There was a segmentation fault bug that happened if a project file was loaded and one of the tracks had a Knob set to a different value. That would trigger a processCCEvent call while the Track was still being loaded, which then would call processInEvent. At the moment processInEvent was called, m_instrument was still NULL, so instrument()->handleMidiEvent caused LMMS to crash. To fix this two measures were taken: 1) Added a sanity check on processInEvent, so it only calls handleMidiEvent if m_instrument is not NULL. 2) During the track being loaded (InstrumentTrack::loadTrackSpecificSettings), we first set m_midiCCEnable to false, so the Knob value changes don't trigger processInEvent calls, then load all knob models and finally load the correct value of m_midiCCEnable. Also added a comment on the InstrumentTrack constructor explaining why the MIDI CC models need to be created before setName (to avoid the position being changed later and a mysterious Segmentation Fault being caused by consequence). --- src/tracks/InstrumentTrack.cpp | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index 396ab061210..4369ad74f30 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -122,6 +122,11 @@ InstrumentTrack::InstrumentTrack( TrackContainer* tc ) : } + // IMPORTANT NOTE: We have to create the MIDI CC models before calling setName, because the latter + // will trigger a trackRenamed signal on the track container, which will then call + // MidiCCRackView::updateTracksComboBox, which itself calls MidiCCRackView::updateKnobsModels. That + // last method expects the Tracks CC Enable and Knob models to be created already. + // Initialize the m_midiCCEnabled variable, but it's actually going to be connected // to a LedButton m_midiCCEnable = new BoolModel( false, NULL, "Enable/Disable MIDI CC" ); @@ -408,7 +413,9 @@ void InstrumentTrack::processInEvent( const MidiEvent& event, const MidiTime& ti break; } - if( eventHandled == false && instrument()->handleMidiEvent( event, time, offset ) == false ) + // If the event wasn't handled, check if there's a loaded instrument and if so send the + // event to it. If it returns false means the instrument didn't handle the event, so we trigger a warning. + if( eventHandled == false && instrument() && instrument()->handleMidiEvent( event, time, offset ) == false ) { qWarning( "InstrumentTrack: unhandled MIDI event %d", event.type() ); } @@ -848,12 +855,13 @@ void InstrumentTrack::loadTrackSpecificSettings( const QDomElement & thisElement m_baseNoteModel.loadSettings( thisElement, "basenote" ); m_useMasterPitchModel.loadSettings( thisElement, "usemasterpitch"); - // Load MIDI CC stuff - m_midiCCEnable->loadSettings( thisElement, "enablecc" ); - // clear effect-chain just in case we load an old preset without FX-data m_audioPort.effects()->clear(); + // We set MIDI CC enable to false so the knobs don't trigger MIDI CC events while + // they are being loaded. After all knobs are loaded we load the right value of m_midiCCEnable. + m_midiCCEnable->setValue(false); + QDomNode node = thisElement.firstChild(); while( !node.isNull() ) { @@ -925,6 +933,10 @@ void InstrumentTrack::loadTrackSpecificSettings( const QDomElement & thisElement } node = node.nextSibling(); } + + // Load the right value of m_midiCCEnable + m_midiCCEnable->loadSettings( thisElement, "enablecc" ); + updatePitchRange(); unlock(); } From 56363bfe1c5a4d083597c7a4371bbc22664aab2a Mon Sep 17 00:00:00 2001 From: IanCaio Date: Sun, 13 Sep 2020 17:42:54 -0300 Subject: [PATCH 21/40] Fixes mistake on processInEvent logic Fixes a mistake on the logic of the last conditional inside processInEvent, where if instrument() returned nullptr a warning wouldn't be triggered even though the MIDI event wasn't handled. --- src/tracks/InstrumentTrack.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index 4369ad74f30..a052017aac7 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -415,7 +415,7 @@ void InstrumentTrack::processInEvent( const MidiEvent& event, const MidiTime& ti // If the event wasn't handled, check if there's a loaded instrument and if so send the // event to it. If it returns false means the instrument didn't handle the event, so we trigger a warning. - if( eventHandled == false && instrument() && instrument()->handleMidiEvent( event, time, offset ) == false ) + if( eventHandled == false && !( instrument() && instrument()->handleMidiEvent( event, time, offset ) ) ) { qWarning( "InstrumentTrack: unhandled MIDI event %d", event.type() ); } From 91d9d0671a893fad9a05f8f5d7f46ad64e17213a Mon Sep 17 00:00:00 2001 From: IanCaio Date: Mon, 14 Sep 2020 19:40:43 -0300 Subject: [PATCH 22/40] Fixes memory leak and "used ID" bug Bug Description: When saving a project with an automation pattern connected to a CC model, then loading another version of the same project the automation lost it connection and a warning was triggered about the ID being used. Motive: Everytime an instrument track was deleted (for example, when loading another project) the models were not being destroyed. That caused a memory leak, and also caused the IDs being used by those models not to be released. So when another project was loaded with the same ID it couldn't be assigned to the appropriate model. Solution: The models related to MIDI CC are now deleted on the instrument track destructor. However, there was a complication to be addressed first: The knobs and ComboBox led from the MIDI Rack are always connected to the selected track's CC models. If we just deleted them, that would cause a Segmentation Fault because the Knobs and LED would try to access an inexistent model. So first we needed to disconnect the Knobs and LED (model views) from our about-to-be-deleted track's CC models. At first, I thought I could just use "setModel( NULL )", since the base class (ModelView.cpp) addresses NULL values. But that also caused a Segmentation Fault, because even though ModelView.cpp accepts NULL models, some classes that inherit from it (like AutomatableModelView) can't handle NULL values for the models. That might be a design flaw that is beyond the scope of this PR, so it will be later discussed with other devs if it should be later fixed. For the sake of simplicity, a "unsetModel" method was created, which calls setModel but to a dummy model (one that is marked as "defaultConstructed", which means on the next call to setModel it will be destroyed). A "unsetModels" method was also added to MidiCCRackView, which basically unsets all models from the MIDI CC rack model views. So now we can go to the instrument track destructor and have the following sequence: - Unset the models on MIDI CC rack view. For that, we first check if the MIDI CC rack view is accessible, because the instrument track destructor is also called when LMMS is being closed, and in that particular situation the MIDI CC rack might not be accessible anymore. - Delete the instrument track models related to MIDI CC - There's no need to directly ask MIDI CC rack to update it's models, because after the destructor finishes a trackRemoved signal will be triggered that will tell MIDI CC rack to update everything anyways. The solution to this bug also fixes the memory leak caused by leaving the model objects hanging. On this commit I also added code on GuiApplication::childDestroyed to assign nullptr to the MIDI CC rack pointer when it's destroyed, as it's done to other children of GuiApplication. --- include/AutomatableModelView.h | 1 + include/MidiCCRackView.h | 1 + include/ModelView.h | 1 + src/gui/AutomatableModelView.cpp | 25 +++++++++++++++++++++++++ src/gui/GuiApplication.cpp | 4 ++++ src/gui/ModelView.cpp | 10 ++++++++++ src/gui/widgets/MidiCCRackView.cpp | 13 +++++++++++++ src/tracks/InstrumentTrack.cpp | 21 +++++++++++++++++++++ 8 files changed, 76 insertions(+) diff --git a/include/AutomatableModelView.h b/include/AutomatableModelView.h index 1bcbd97d6fe..b3a935d39b1 100644 --- a/include/AutomatableModelView.h +++ b/include/AutomatableModelView.h @@ -50,6 +50,7 @@ class LMMS_EXPORT AutomatableModelView : public ModelView } void setModel( Model* model, bool isOldModelValid = true ) override; + void unsetModel() override; template inline T value() const diff --git a/include/MidiCCRackView.h b/include/MidiCCRackView.h index 03cb1d8d068..2d767938ca3 100644 --- a/include/MidiCCRackView.h +++ b/include/MidiCCRackView.h @@ -33,6 +33,7 @@ class MidiCCRackView : public QWidget, public SerializingObject public slots: void updateTracksComboBox(); void updateKnobsModels(); + void unsetModels(); private: ComboBox *m_trackComboBox; diff --git a/include/ModelView.h b/include/ModelView.h index 907cd14efdf..04229ed0d2f 100644 --- a/include/ModelView.h +++ b/include/ModelView.h @@ -36,6 +36,7 @@ class LMMS_EXPORT ModelView virtual ~ModelView(); virtual void setModel( Model* model, bool isOldModelValid = true ); + virtual void unsetModel(); Model* model() { diff --git a/src/gui/AutomatableModelView.cpp b/src/gui/AutomatableModelView.cpp index 039c75c9953..104adf19c10 100644 --- a/src/gui/AutomatableModelView.cpp +++ b/src/gui/AutomatableModelView.cpp @@ -141,6 +141,31 @@ void AutomatableModelView::setModel( Model* model, bool isOldModelValid ) +// Unsets the current model by setting a dummy empty model. The dummy model is marked as +// "defaultConstructed", so the next call to setModel will delete it. +void AutomatableModelView::unsetModel() +{ + if( dynamic_cast( this ) ) + { + setModel( new FloatModel( 0, 0, 0, 1, NULL, QString(), true ) ); + } + else if( dynamic_cast( this ) ) + { + setModel( new IntModel( 0, 0, 0, NULL, QString(), true ) ); + } + else if( dynamic_cast( this ) ) + { + setModel( new BoolModel( false, NULL, QString(), true ) ); + } + else + { + ModelView::unsetModel(); + } +} + + + + void AutomatableModelView::mousePressEvent( QMouseEvent* event ) { if( event->button() == Qt::LeftButton && event->modifiers() & Qt::ControlModifier ) diff --git a/src/gui/GuiApplication.cpp b/src/gui/GuiApplication.cpp index 50f8595eb51..9409d65f87d 100644 --- a/src/gui/GuiApplication.cpp +++ b/src/gui/GuiApplication.cpp @@ -215,4 +215,8 @@ void GuiApplication::childDestroyed(QObject *obj) { m_controllerRackView = nullptr; } + else if (obj == m_midiCCRackView) + { + m_midiCCRackView = nullptr; + } } diff --git a/src/gui/ModelView.cpp b/src/gui/ModelView.cpp index 3b250fbcd3f..061750caec4 100644 --- a/src/gui/ModelView.cpp +++ b/src/gui/ModelView.cpp @@ -74,6 +74,16 @@ void ModelView::setModel( Model* model, bool isOldModelValid ) +// Unsets the current model by setting a dummy empty model. The dummy model is marked as +// "defaultConstructed", so the next call to setModel will delete it. +void ModelView::unsetModel() +{ + setModel( new Model( NULL, QString(), true ) ); +} + + + + void ModelView::doConnections() { if( m_model != NULL ) diff --git a/src/gui/widgets/MidiCCRackView.cpp b/src/gui/widgets/MidiCCRackView.cpp index 19d691b3acd..e9a90d1e865 100644 --- a/src/gui/widgets/MidiCCRackView.cpp +++ b/src/gui/widgets/MidiCCRackView.cpp @@ -190,6 +190,9 @@ void MidiCCRackView::updateTracksComboBox() void MidiCCRackView::updateKnobsModels() { + // Disconnect the model views from any model first + unsetModels(); + if( m_tracks.size() > 0 ) { InstrumentTrack *selectedTrack = dynamic_cast( m_tracks[ m_trackComboBoxModel->value() ] ); @@ -211,6 +214,16 @@ void MidiCCRackView::updateKnobsModels() } } +void MidiCCRackView::unsetModels() +{ + m_midiCCGroupBox->unsetModel(); + + for( int i = 0; i < MidiControllerCount; ++i ) + { + m_controllerKnob[i]->unsetModel(); + } +} + void MidiCCRackView::saveSettings( QDomDocument & _doc, QDomElement & _this ) { diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index a052017aac7..b48abf248c3 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -164,6 +164,27 @@ int InstrumentTrack::baseNote() const InstrumentTrack::~InstrumentTrack() { + // Delete models from the MIDI CC + // First unset the models from the MIDI CC rack in case ours are being used + // OBS: We need to check if getMidiCCRackView() is not nullptr because the track might be + // destroyed during LMMS being closed, where the editors and racks could have been destroyed + // already. + if( GuiApplication::instance()->getMidiCCRackView() ) + { + GuiApplication::instance()->getMidiCCRackView()->unsetModels(); + } + + // Remove the models + delete m_midiCCEnable; + + for( int i = 0; i < MidiControllerCount; ++i ) + { + delete m_midiCCModel[i]; + } + + // We don't need to call gui->getMidiCCRackView()->updateKnobsModels() because it will be called + // automatically when the trackRemoved signal is triggered. + // De-assign midi device if (m_hasAutoMidiDev) { From 39c21b658ef7ef66b8d88116043ce80728f0c4e8 Mon Sep 17 00:00:00 2001 From: IanCaio Date: Mon, 21 Sep 2020 01:00:17 -0300 Subject: [PATCH 23/40] Changes MIDI CC Rack GUI Instead of having a single window being shared by all instruments, this commit starts working towards having one MIDI CC Rack for each instrument. To start making that the following changes were made to the code: - Removed MIDI CC Rack from GuiApplication.cpp and MainWindow.cpp - Added a MidiCCRackView to each InstrumentTrackView, along with a toggleMidiCCRack method. - Changes the MidiCCRackView class. The constructor now takes a track that is going to be associated with that rack. updateTracksComboBox and updateKnobsModels methods were removed since they are not necessary anymore now that each track will have its own MIDI CC rack. Adds destroyRack and renameLabel methods, so the rack can update itself when the track changes name or gets removed. - Creates an entry on the MIDI section of the TrackView context menu that Opens/Closes the MIDI CC rack for that track. - Small indentation fix on InstrumentTrack.cpp TODO: - Change the way CC rack events are handled so they don't get ignored during export. --- include/GuiApplication.h | 3 - include/InstrumentTrack.h | 4 + include/MainWindow.h | 1 - include/MidiCCRackView.h | 13 ++-- src/gui/GuiApplication.cpp | 9 --- src/gui/MainWindow.cpp | 22 ------ src/gui/widgets/MidiCCRackView.cpp | 121 +++++++---------------------- src/tracks/InstrumentTrack.cpp | 44 ++++++----- 8 files changed, 62 insertions(+), 155 deletions(-) diff --git a/include/GuiApplication.h b/include/GuiApplication.h index 0752dffd6e4..8b4284c026b 100644 --- a/include/GuiApplication.h +++ b/include/GuiApplication.h @@ -39,7 +39,6 @@ class MainWindow; class PianoRollWindow; class ProjectNotes; class SongEditorWindow; -class MidiCCRackView; class LMMS_EXPORT GuiApplication : public QObject { @@ -58,7 +57,6 @@ class LMMS_EXPORT GuiApplication : public QObject ProjectNotes* getProjectNotes() { return m_projectNotes; } AutomationEditorWindow* automationEditor() { return m_automationEditor; } ControllerRackView* getControllerRackView() { return m_controllerRackView; } - MidiCCRackView* getMidiCCRackView() { return m_midiCCRackView; } public slots: void displayInitProgress(const QString &msg); @@ -77,7 +75,6 @@ private slots: PianoRollWindow* m_pianoRoll; ProjectNotes* m_projectNotes; ControllerRackView* m_controllerRackView; - MidiCCRackView* m_midiCCRackView; QLabel* m_loadingProgressLabel; }; diff --git a/include/InstrumentTrack.h b/include/InstrumentTrack.h index 96a8d4299fa..4363fc82177 100644 --- a/include/InstrumentTrack.h +++ b/include/InstrumentTrack.h @@ -39,6 +39,7 @@ #include "Plugin.h" #include "Track.h" #include "Midi.h" +#include "MidiCCRackView.h" @@ -345,6 +346,7 @@ class InstrumentTrackView : public TrackView private slots: void toggleInstrumentWindow( bool _on ); + void toggleMidiCCRack(); void activityIndicatorPressed(); void activityIndicatorReleased(); @@ -372,6 +374,8 @@ private slots: QAction * m_midiInputAction; QAction * m_midiOutputAction; + MidiCCRackView * m_midiCCRackView; + QPoint m_lastPos; FadeButton * getActivityIndicator() diff --git a/include/MainWindow.h b/include/MainWindow.h index 42c895cf2bf..a179e651e49 100644 --- a/include/MainWindow.h +++ b/include/MainWindow.h @@ -156,7 +156,6 @@ public slots: void togglePianoRollWin(); void toggleControllerRack(); void toggleFullscreen(); - void toggleMidiCCRack(); void updatePlayPauseIcons(); diff --git a/include/MidiCCRackView.h b/include/MidiCCRackView.h index 2d767938ca3..943bb422fb0 100644 --- a/include/MidiCCRackView.h +++ b/include/MidiCCRackView.h @@ -2,6 +2,7 @@ #define MIDI_CC_RACK_VIEW_H #include +#include #include #include "SerializingObject.h" @@ -19,7 +20,7 @@ class MidiCCRackView : public QWidget, public SerializingObject { Q_OBJECT public: - MidiCCRackView(); + MidiCCRackView( InstrumentTrack * track ); virtual ~MidiCCRackView(); void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override; @@ -31,14 +32,14 @@ class MidiCCRackView : public QWidget, public SerializingObject } public slots: - void updateTracksComboBox(); - void updateKnobsModels(); void unsetModels(); + void destroyRack(); + void renameLabel(); private: - ComboBox *m_trackComboBox; - ComboBoxModel *m_trackComboBoxModel; - TrackContainer::TrackList m_tracks; // List with pointers to the ComboBox tracks themselfs + QLabel *m_trackLabel; + + InstrumentTrack *m_track; GroupBox *m_midiCCGroupBox; // MIDI CC GroupBox (used to enable disable MIDI CC) diff --git a/src/gui/GuiApplication.cpp b/src/gui/GuiApplication.cpp index 9409d65f87d..fb2e3eae376 100644 --- a/src/gui/GuiApplication.cpp +++ b/src/gui/GuiApplication.cpp @@ -38,7 +38,6 @@ #include "PianoRoll.h" #include "ProjectNotes.h" #include "SongEditor.h" -#include "MidiCCRackView.h" #include #include @@ -152,10 +151,6 @@ GuiApplication::GuiApplication() m_automationEditor = new AutomationEditorWindow; connect(m_automationEditor, SIGNAL(destroyed(QObject*)), this, SLOT(childDestroyed(QObject*))); - displayInitProgress(tr("Preparing MIDI CC rack")); - m_midiCCRackView = new MidiCCRackView; - connect(m_midiCCRackView, SIGNAL(destroyed(QObject*)), this, SLOT(childDestroyed(QObject*))); - splashScreen.finish(m_mainWindow); m_mainWindow->finalize(); @@ -215,8 +210,4 @@ void GuiApplication::childDestroyed(QObject *obj) { m_controllerRackView = nullptr; } - else if (obj == m_midiCCRackView) - { - m_midiCCRackView = nullptr; - } } diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index 930c2904a1a..94f337576ed 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -42,7 +42,6 @@ #include "AutomationEditor.h" #include "BBEditor.h" #include "ControllerRackView.h" -#include "MidiCCRackView.h" #include "embed.h" #include "Engine.h" #include "ExportProjectDialog.h" @@ -538,14 +537,6 @@ void MainWindow::finalize() m_toolBar ); project_notes_window->setShortcut( Qt::CTRL + Qt::Key_7 ); - ToolButton * midi_cc_rack_window = new ToolButton( - embed::getIconPixmap( "midi_cc_rack" ), - tr( "Show/hide MIDI CC rack") + - " (Ctrl+8)", - this, SLOT( toggleMidiCCRack() ), - m_toolBar ); - midi_cc_rack_window->setShortcut( Qt::CTRL + Qt::Key_8 ); - m_toolBarLayout->addWidget( song_editor_window, 1, 1 ); m_toolBarLayout->addWidget( bb_editor_window, 1, 2 ); m_toolBarLayout->addWidget( piano_roll_window, 1, 3 ); @@ -553,7 +544,6 @@ void MainWindow::finalize() m_toolBarLayout->addWidget( fx_mixer_window, 1, 5 ); m_toolBarLayout->addWidget( controllers_window, 1, 6 ); m_toolBarLayout->addWidget( project_notes_window, 1, 7 ); - m_toolBarLayout->addWidget( midi_cc_rack_window, 1, 8 ); m_toolBarLayout->setColumnStretch( 100, 1 ); // setup-dialog opened before? @@ -1148,10 +1138,6 @@ void MainWindow::updateViewMenu() tr( "Project Notes" ) + "\tCtrl+7", this, SLOT( toggleProjectNotesWin() ) ); - m_viewMenu->addAction(embed::getIconPixmap( "midi_cc_rack" ), - tr( "MIDI CC Rack" ) + "\tCtrl+8", - this, SLOT( toggleMidiCCRack() ) - ); m_viewMenu->addSeparator(); @@ -1257,14 +1243,6 @@ void MainWindow::toggleControllerRack() -void MainWindow::toggleMidiCCRack() -{ - toggleWindow( gui->getMidiCCRackView() ); -} - - - - void MainWindow::updatePlayPauseIcons() { gui->songEditor()->setPauseIcon( false ); diff --git a/src/gui/widgets/MidiCCRackView.cpp b/src/gui/widgets/MidiCCRackView.cpp index e9a90d1e865..62994258e47 100644 --- a/src/gui/widgets/MidiCCRackView.cpp +++ b/src/gui/widgets/MidiCCRackView.cpp @@ -49,8 +49,9 @@ #include "BBEditor.h" -MidiCCRackView::MidiCCRackView() : - QWidget() +MidiCCRackView::MidiCCRackView( InstrumentTrack * track ) : + QWidget(), + m_track( track ) { setWindowIcon( embed::getIconPixmap( "midi_cc_rack" ) ); setWindowTitle( tr("MIDI CC Rack") ); @@ -77,15 +78,9 @@ MidiCCRackView::MidiCCRackView() : // We use a widget to be able to make this layout have a fixed height QWidget *trackToolBar = new QWidget(); QHBoxLayout *trackToolBarLayout = new QHBoxLayout( trackToolBar ); - QLabel *trackLabel = new QLabel( tr("Track: ") ); - m_trackComboBox = new ComboBox(); - m_trackComboBoxModel = new ComboBoxModel(); - m_trackComboBox->setModel(m_trackComboBoxModel); - - trackToolBarLayout->addWidget(trackLabel); - trackToolBarLayout->addWidget(m_trackComboBox); - trackToolBarLayout->setStretchFactor( trackLabel, 1 ); - trackToolBarLayout->setStretchFactor( m_trackComboBox, 2 ); + m_trackLabel = new QLabel( QString( tr( "Track: %1" ) ).arg( m_track->name() ) ); + + trackToolBarLayout->addWidget(m_trackLabel); trackToolBar->setFixedHeight(40); // Knobs GroupBox - Here we have the MIDI CC controller knobs for the selected track @@ -115,31 +110,22 @@ MidiCCRackView::MidiCCRackView() : knobsAreaLayout->addWidget( m_controllerKnob[i], i/3, i%3 ); } - // Connections are made to make sure the track ComboBox is updated when tracks are - // added, removed or renamed - // On the song editor: - connect( Engine::getSong() , SIGNAL( trackAdded(Track *) ), - this, SLOT( updateTracksComboBox() ) ); - connect( Engine::getSong() , SIGNAL( trackRemoved() ), - this, SLOT( updateTracksComboBox() ) ); - connect( Engine::getSong() , SIGNAL( trackRenamed() ), - this, SLOT( updateTracksComboBox() ) ); - // On the BB editor: - connect( Engine::getBBTrackContainer() , SIGNAL( trackAdded(Track *) ), - this, SLOT( updateTracksComboBox() ) ); - connect( Engine::getBBTrackContainer() , SIGNAL( trackRemoved() ), - this, SLOT( updateTracksComboBox() ) ); - connect( Engine::getBBTrackContainer() , SIGNAL( trackRenamed() ), - this, SLOT( updateTracksComboBox() ) ); - // Also when tracks are moved on the song editor and BB editor - connect( gui->songEditor()->m_editor, SIGNAL( movedTrackView() ), - this, SLOT( updateTracksComboBox() ) ); - connect( gui->getBBEditor()->trackContainerView(), SIGNAL( movedTrackView() ), - this, SLOT( updateTracksComboBox() ) ); - - // Connection to update the knobs when the ComboBox selects another track - connect( m_trackComboBoxModel, SIGNAL( dataChanged() ), - this, SLOT( updateKnobsModels() )); + // Set all the models + // Set the LED button to enable/disable the track midi cc + m_midiCCGroupBox->setModel( m_track->m_midiCCEnable ); + + // Set the model for each Knob + for( int i = 0; i < MidiControllerCount; ++i ){ + m_controllerKnob[i]->setModel( m_track->m_midiCCModel[i] ); + } + + // Connection made to make sure the rack is destroyed if the track is destroyed + connect( m_track, SIGNAL( destroyedTrack() ), + this, SLOT( destroyRack() ) ); + + // Connection to update the name of the track on the label + connect( m_track, SIGNAL( nameChanged() ), + this, SLOT( renameLabel() ) ); // Adding everything to the main layout mainLayout->addWidget(trackToolBar); @@ -150,68 +136,15 @@ MidiCCRackView::~MidiCCRackView() { } -void MidiCCRackView::updateTracksComboBox() +void MidiCCRackView::destroyRack() { - // Reset the combo box model to fill it with instrument tracks from the song/BB editors - m_trackComboBoxModel->clear(); - - // Reset our list with pointers to the tracks - m_tracks.clear(); - - TrackContainer::TrackList songEditorTracks; - songEditorTracks = Engine::getSong()->tracks(); - int songEditorID = 1; - - TrackContainer::TrackList bbEditorTracks; - bbEditorTracks = Engine::getBBTrackContainer()->tracks(); - int bbEditorID = 1; - - for(Track *t: songEditorTracks) - { - if( t->type() == Track::InstrumentTrack ) - { - m_trackComboBoxModel->addItem("SongEditor: " + QString::number(songEditorID) + ". " + t->name()); - m_tracks += t; - ++songEditorID; - } - } - for(Track *t: bbEditorTracks) - { - if( t->type() == Track::InstrumentTrack ) - { - m_trackComboBoxModel->addItem("BBEditor: " + QString::number(bbEditorID) + ". " + t->name()); - m_tracks += t; - ++bbEditorID; - } - } - - updateKnobsModels(); + unsetModels(); + parentWidget()->close(); } -void MidiCCRackView::updateKnobsModels() +void MidiCCRackView::renameLabel() { - // Disconnect the model views from any model first - unsetModels(); - - if( m_tracks.size() > 0 ) - { - InstrumentTrack *selectedTrack = dynamic_cast( m_tracks[ m_trackComboBoxModel->value() ] ); - - // TODO: I need to figure out why this line is necessary. Without it I get a segfault because at - // LMMS's startup sometimes m_tracks will hold tracks that have type() == Tracks::InstrumentTracks - // but casting the to InstrumentTrack * returns a nullptr. Meaning maybe the constructor wasn't - // executed yet. - if( selectedTrack ) - { - // Set the LED button to enable/disable the track midi cc - m_midiCCGroupBox->setModel( selectedTrack->m_midiCCEnable ); - - // Set the model for each Knob - for( int i = 0; i < MidiControllerCount; ++i ){ - m_controllerKnob[i]->setModel( selectedTrack->m_midiCCModel[i] ); - } - } - } + m_trackLabel->setText( QString( tr( "Track: %1" ) ).arg( m_track->name() ) ); } void MidiCCRackView::unsetModels() diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index b48abf248c3..c690e390aea 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -122,11 +122,6 @@ InstrumentTrack::InstrumentTrack( TrackContainer* tc ) : } - // IMPORTANT NOTE: We have to create the MIDI CC models before calling setName, because the latter - // will trigger a trackRenamed signal on the track container, which will then call - // MidiCCRackView::updateTracksComboBox, which itself calls MidiCCRackView::updateKnobsModels. That - // last method expects the Tracks CC Enable and Knob models to be created already. - // Initialize the m_midiCCEnabled variable, but it's actually going to be connected // to a LedButton m_midiCCEnable = new BoolModel( false, NULL, "Enable/Disable MIDI CC" ); @@ -164,17 +159,7 @@ int InstrumentTrack::baseNote() const InstrumentTrack::~InstrumentTrack() { - // Delete models from the MIDI CC - // First unset the models from the MIDI CC rack in case ours are being used - // OBS: We need to check if getMidiCCRackView() is not nullptr because the track might be - // destroyed during LMMS being closed, where the editors and racks could have been destroyed - // already. - if( GuiApplication::instance()->getMidiCCRackView() ) - { - GuiApplication::instance()->getMidiCCRackView()->unsetModels(); - } - - // Remove the models + // Remove the MIDI CC models delete m_midiCCEnable; for( int i = 0; i < MidiControllerCount; ++i ) @@ -182,9 +167,6 @@ InstrumentTrack::~InstrumentTrack() delete m_midiCCModel[i]; } - // We don't need to call gui->getMidiCCRackView()->updateKnobsModels() because it will be called - // automatically when the trackRemoved signal is triggered. - // De-assign midi device if (m_hasAutoMidiDev) { @@ -1093,11 +1075,13 @@ InstrumentTrackView::InstrumentTrackView( InstrumentTrack * _it, TrackContainerV m_panningKnob = new Knob( knobSmall_17, getTrackSettingsWidget(), tr( "Panning" ) ); m_panningKnob->setModel( &_it->m_panningModel ); - m_panningKnob->setHintText( tr( "Panning:" ), "%" ); + m_panningKnob->setHintText( tr( "Panning:" ), "%" ); m_panningKnob->move( widgetWidth-24, 2 ); m_panningKnob->setLabel( tr( "PAN" ) ); m_panningKnob->show(); + m_midiCCRackView = new MidiCCRackView( _it ); + m_midiMenu = new QMenu( tr( "MIDI" ), this ); // sequenced MIDI? @@ -1133,6 +1117,10 @@ InstrumentTrackView::InstrumentTrackView( InstrumentTrack * _it, TrackContainerV m_midiInputAction->setText( tr( "Input" ) ); m_midiOutputAction->setText( tr( "Output" ) ); + QAction *midiRackAction = m_midiMenu->addAction( "Open/Close MIDI CC Rack" ); + connect( midiRackAction, SIGNAL( triggered() ), + this, SLOT( toggleMidiCCRack() ) ); + m_activityIndicator = new FadeButton( QApplication::palette().color( QPalette::Active, QPalette::Background), QApplication::palette().color( QPalette::Active, @@ -1169,6 +1157,22 @@ InstrumentTrackView::~InstrumentTrackView() +void InstrumentTrackView::toggleMidiCCRack() +{ + if( m_midiCCRackView->parentWidget()->isVisible() ) + { + m_midiCCRackView->parentWidget()->hide(); + } + else + { + m_midiCCRackView->parentWidget()->show(); + m_midiCCRackView->show(); + } +} + + + + InstrumentTrackWindow * InstrumentTrackView::topLevelInstrumentTrackWindow() { InstrumentTrackWindow * w = NULL; From b3e2479f9c9d94b090eccbfa408d7d0bd1403fe2 Mon Sep 17 00:00:00 2001 From: IanCaio Date: Mon, 21 Sep 2020 17:00:33 -0300 Subject: [PATCH 24/40] Fixes bug where CC events are ignored on export Because they are being processed as input events, the CC events were being ignored on processInEvent, so automations would work fine on playback but would not on the final rendered file. This commit fixes it by adding a property to the MidiEvent class called fromHardware, which signals if an event should be processed as if it were generated by a hardware controller (thus ignored on the export) or not. All the constructors have that property added as an argument that defaults to true, so all MidiEvents used so far will have fromHardware set to true. The processCCEvent method now creates a MidiEvent with fromHardware set to false, so it can be processed. ToDo: - I'm not 100% happy with the property name. "fromHardware" implies that the event was actually generated by hardware, which at some situations might not be true (it would just be ignored on processInEvent as if it were). I'm still thinking of other alternatives, like "ignoreOnExport" or something similar, but that's something that can easily be changed later. --- include/MidiEvent.h | 27 +++++++++++++++++++++------ src/tracks/InstrumentTrack.cpp | 7 ++++--- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/include/MidiEvent.h b/include/MidiEvent.h index 907314b4866..d6b0e5f2ebb 100644 --- a/include/MidiEvent.h +++ b/include/MidiEvent.h @@ -37,34 +37,38 @@ class MidiEvent int8_t channel = 0, int16_t param1 = 0, int16_t param2 = 0, - const void* sourcePort = NULL ) : + const void* sourcePort = NULL, + bool fromHardware = true ) : m_type( type ), m_metaEvent( MidiMetaInvalid ), m_channel( channel ), m_sysExData( NULL ), - m_sourcePort( sourcePort ) + m_sourcePort( sourcePort ), + m_fromHardware( fromHardware ) { m_data.m_param[0] = param1; m_data.m_param[1] = param2; } - MidiEvent( MidiEventTypes type, const char* sysExData, int dataLen ) : + MidiEvent( MidiEventTypes type, const char* sysExData, int dataLen, bool fromHardware = true ) : m_type( type ), m_metaEvent( MidiMetaInvalid ), m_channel( 0 ), m_sysExData( sysExData ), - m_sourcePort( NULL ) + m_sourcePort( NULL ), + m_fromHardware( fromHardware ) { m_data.m_sysExDataLen = dataLen; } - MidiEvent( const MidiEvent& other ) : + MidiEvent( const MidiEvent& other, bool fromHardware = true ) : m_type( other.m_type ), m_metaEvent( other.m_metaEvent ), m_channel( other.m_channel ), m_data( other.m_data ), m_sysExData( other.m_sysExData ), - m_sourcePort( other.m_sourcePort ) + m_sourcePort( other.m_sourcePort ), + m_fromHardware( fromHardware ) { } @@ -190,6 +194,16 @@ class MidiEvent setParam( 0, pitchBend ); } + bool fromHardware() const + { + return m_fromHardware; + } + + void setHardware( bool value ) + { + m_fromHardware = value; + } + private: MidiEventTypes m_type; // MIDI event type @@ -204,6 +218,7 @@ class MidiEvent const char* m_sysExData; const void* m_sourcePort; + bool m_fromHardware; // Should the event be treated as originated from a physical controller? } ; diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index c690e390aea..e4230d2420d 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -278,8 +278,9 @@ void InstrumentTrack::processCCEvent(int controller) uint16_t cc = static_cast( controller ); uint16_t value = static_cast( m_midiCCModel[ controller ]->value() ); - // Process the MIDI CC event as if it was generated by a physical MIDI controller - processInEvent( MidiEvent( MidiControlChange, channel, cc, value ) ); + // Process the MIDI CC event as an input event but with fromHardware set to false + // so we can know LMMS generated the event, not a controller. + processInEvent( MidiEvent( MidiControlChange, channel, cc, value, NULL, false ) ); } @@ -287,7 +288,7 @@ void InstrumentTrack::processCCEvent(int controller) void InstrumentTrack::processInEvent( const MidiEvent& event, const MidiTime& time, f_cnt_t offset ) { - if( Engine::getSong()->isExporting() ) + if( Engine::getSong()->isExporting() && event.fromHardware() ) { return; } From 527a95931f2a67f293af2f457ead02e0cbbb931d Mon Sep 17 00:00:00 2001 From: IanCaio Date: Tue, 22 Sep 2020 00:46:11 -0300 Subject: [PATCH 25/40] Removes argument from MidiEvent copy constructor Removes an unnecessary argument I added on the copy constructor of MidiEvent, since its value should be copied from the source event. --- include/MidiEvent.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/MidiEvent.h b/include/MidiEvent.h index d6b0e5f2ebb..2d68ee614b0 100644 --- a/include/MidiEvent.h +++ b/include/MidiEvent.h @@ -61,14 +61,14 @@ class MidiEvent m_data.m_sysExDataLen = dataLen; } - MidiEvent( const MidiEvent& other, bool fromHardware = true ) : + MidiEvent( const MidiEvent& other ) : m_type( other.m_type ), m_metaEvent( other.m_metaEvent ), m_channel( other.m_channel ), m_data( other.m_data ), m_sysExData( other.m_sysExData ), m_sourcePort( other.m_sourcePort ), - m_fromHardware( fromHardware ) + m_fromHardware( other.m_fromHardware ) { } From b8081a4b890f333acfe7f351a94d99ada2bd7eac Mon Sep 17 00:00:00 2001 From: Ian Caio Date: Mon, 16 Nov 2020 17:04:03 -0300 Subject: [PATCH 26/40] Changes variable fromHardware to ignoreOnExport Changes name of the variable fromHardware to ignoreOnExport on the MidiEvent class. The name better represents its intention. Also fixes formatting issues throughout the files changed on this PR (mostly spacing and changing NULL to nullptr). --- include/MidiCCRackView.h | 6 +-- include/MidiEvent.h | 33 +++++++------- src/core/TrackContainer.cpp | 4 +- src/gui/AutomatableModelView.cpp | 12 ++--- src/gui/ModelView.cpp | 2 +- src/gui/widgets/MidiCCRackView.cpp | 71 +++++++++++++++--------------- src/tracks/InstrumentTrack.cpp | 62 +++++++++++++------------- 7 files changed, 94 insertions(+), 96 deletions(-) diff --git a/include/MidiCCRackView.h b/include/MidiCCRackView.h index 943bb422fb0..de30c53089a 100644 --- a/include/MidiCCRackView.h +++ b/include/MidiCCRackView.h @@ -20,11 +20,11 @@ class MidiCCRackView : public QWidget, public SerializingObject { Q_OBJECT public: - MidiCCRackView( InstrumentTrack * track ); + MidiCCRackView(InstrumentTrack * track); virtual ~MidiCCRackView(); - void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override; - void loadSettings( const QDomElement & _this ) override; + void saveSettings(QDomDocument & doc, QDomElement & parent) override; + void loadSettings(const QDomElement &) override; inline QString nodeName() const override { diff --git a/include/MidiEvent.h b/include/MidiEvent.h index 2d68ee614b0..8e37fe23975 100644 --- a/include/MidiEvent.h +++ b/include/MidiEvent.h @@ -33,30 +33,30 @@ class MidiEvent { public: - MidiEvent( MidiEventTypes type = MidiActiveSensing, + MidiEvent(MidiEventTypes type = MidiActiveSensing, int8_t channel = 0, int16_t param1 = 0, int16_t param2 = 0, - const void* sourcePort = NULL, - bool fromHardware = true ) : + const void* sourcePort = nullptr, + bool ignoreOnExport = true) : m_type( type ), m_metaEvent( MidiMetaInvalid ), m_channel( channel ), m_sysExData( NULL ), - m_sourcePort( sourcePort ), - m_fromHardware( fromHardware ) + m_sourcePort(sourcePort), + m_ignoreOnExport(ignoreOnExport) { m_data.m_param[0] = param1; m_data.m_param[1] = param2; } - MidiEvent( MidiEventTypes type, const char* sysExData, int dataLen, bool fromHardware = true ) : + MidiEvent(MidiEventTypes type, const char* sysExData, int dataLen, bool ignoreOnExport = true) : m_type( type ), m_metaEvent( MidiMetaInvalid ), m_channel( 0 ), m_sysExData( sysExData ), - m_sourcePort( NULL ), - m_fromHardware( fromHardware ) + m_sourcePort(nullptr), + m_ignoreOnExport(ignoreOnExport) { m_data.m_sysExDataLen = dataLen; } @@ -67,8 +67,8 @@ class MidiEvent m_channel( other.m_channel ), m_data( other.m_data ), m_sysExData( other.m_sysExData ), - m_sourcePort( other.m_sourcePort ), - m_fromHardware( other.m_fromHardware ) + m_sourcePort(other.m_sourcePort), + m_ignoreOnExport(other.m_ignoreOnExport) { } @@ -194,14 +194,14 @@ class MidiEvent setParam( 0, pitchBend ); } - bool fromHardware() const + bool ignoreOnExport() const { - return m_fromHardware; + return m_ignoreOnExport; } - void setHardware( bool value ) + void setIgnoreOnExport(bool value) { - m_fromHardware = value; + m_ignoreOnExport = value; } @@ -218,8 +218,9 @@ class MidiEvent const char* m_sysExData; const void* m_sourcePort; - bool m_fromHardware; // Should the event be treated as originated from a physical controller? - + bool m_ignoreOnExport; // Should we ignore this MIDI event when exporting a project? + // This helps us ignoring MIDI events that shouldn't be processed + // during a project export, like physical controller events. } ; #endif diff --git a/src/core/TrackContainer.cpp b/src/core/TrackContainer.cpp index 1aabf279094..33be024c75f 100644 --- a/src/core/TrackContainer.cpp +++ b/src/core/TrackContainer.cpp @@ -182,8 +182,8 @@ void TrackContainer::addTrack( Track * _track ) _track->unlock(); emit trackAdded( _track ); - connect( _track, SIGNAL( nameChanged() ), - this, SIGNAL( trackRenamed() ) ); + connect(_track, SIGNAL(nameChanged()), + this, SIGNAL(trackRenamed())); } } diff --git a/src/gui/AutomatableModelView.cpp b/src/gui/AutomatableModelView.cpp index 104adf19c10..a09b11f403f 100644 --- a/src/gui/AutomatableModelView.cpp +++ b/src/gui/AutomatableModelView.cpp @@ -145,17 +145,17 @@ void AutomatableModelView::setModel( Model* model, bool isOldModelValid ) // "defaultConstructed", so the next call to setModel will delete it. void AutomatableModelView::unsetModel() { - if( dynamic_cast( this ) ) + if (dynamic_cast(this)) { - setModel( new FloatModel( 0, 0, 0, 1, NULL, QString(), true ) ); + setModel(new FloatModel( 0, 0, 0, 1, nullptr, QString(), true)); } - else if( dynamic_cast( this ) ) + else if (dynamic_cast(this)) { - setModel( new IntModel( 0, 0, 0, NULL, QString(), true ) ); + setModel(new IntModel(0, 0, 0, nullptr, QString(), true)); } - else if( dynamic_cast( this ) ) + else if (dynamic_cast(this)) { - setModel( new BoolModel( false, NULL, QString(), true ) ); + setModel(new BoolModel(false, nullptr, QString(), true)); } else { diff --git a/src/gui/ModelView.cpp b/src/gui/ModelView.cpp index 061750caec4..f9031ea9484 100644 --- a/src/gui/ModelView.cpp +++ b/src/gui/ModelView.cpp @@ -78,7 +78,7 @@ void ModelView::setModel( Model* model, bool isOldModelValid ) // "defaultConstructed", so the next call to setModel will delete it. void ModelView::unsetModel() { - setModel( new Model( NULL, QString(), true ) ); + setModel(new Model(nullptr, QString(), true)); } diff --git a/src/gui/widgets/MidiCCRackView.cpp b/src/gui/widgets/MidiCCRackView.cpp index 62994258e47..342a92c5271 100644 --- a/src/gui/widgets/MidiCCRackView.cpp +++ b/src/gui/widgets/MidiCCRackView.cpp @@ -49,46 +49,46 @@ #include "BBEditor.h" -MidiCCRackView::MidiCCRackView( InstrumentTrack * track ) : +MidiCCRackView::MidiCCRackView(InstrumentTrack * track) : QWidget(), - m_track( track ) + m_track(track) { - setWindowIcon( embed::getIconPixmap( "midi_cc_rack" ) ); - setWindowTitle( tr("MIDI CC Rack") ); + setWindowIcon(embed::getIconPixmap("midi_cc_rack")); + setWindowTitle(tr("MIDI CC Rack")); - QMdiSubWindow * subWin = gui->mainWindow()->addWindowedWidget( this ); + QMdiSubWindow * subWin = gui->mainWindow()->addWindowedWidget(this); // Remove maximize button Qt::WindowFlags flags = subWin->windowFlags(); flags &= ~Qt::WindowMaximizeButtonHint; - subWin->setWindowFlags( flags ); + subWin->setWindowFlags(flags); // Adjust window attributes, sizing and position - subWin->setAttribute( Qt::WA_DeleteOnClose, false ); - subWin->move( 780, 50 ); - subWin->resize( 350, 300 ); - subWin->setFixedWidth( 350 ); - subWin->setMinimumHeight( 300 ); + subWin->setAttribute(Qt::WA_DeleteOnClose, false); + subWin->move(780, 50); + subWin->resize(350, 300); + subWin->setFixedWidth(350); + subWin->setMinimumHeight(300); subWin->hide(); // Main window layout - QVBoxLayout *mainLayout = new QVBoxLayout( this ); + QVBoxLayout *mainLayout = new QVBoxLayout(this); - // Track Selector Layout - Here we select which track we are sending CC messages to + // Track name label layout // We use a widget to be able to make this layout have a fixed height QWidget *trackToolBar = new QWidget(); - QHBoxLayout *trackToolBarLayout = new QHBoxLayout( trackToolBar ); - m_trackLabel = new QLabel( QString( tr( "Track: %1" ) ).arg( m_track->name() ) ); + QHBoxLayout *trackToolBarLayout = new QHBoxLayout(trackToolBar); + m_trackLabel = new QLabel(QString(tr("Track: %1")).arg(m_track->name())); trackToolBarLayout->addWidget(m_trackLabel); trackToolBar->setFixedHeight(40); // Knobs GroupBox - Here we have the MIDI CC controller knobs for the selected track - m_midiCCGroupBox = new GroupBox( tr("MIDI CC Knobs:") ); + m_midiCCGroupBox = new GroupBox(tr("MIDI CC Knobs:")); // Layout to keep scrollable area under the GroupBox header QVBoxLayout *knobsGroupBoxLayout = new QVBoxLayout(); - knobsGroupBoxLayout->setContentsMargins( 5, 16, 5, 5 ); + knobsGroupBoxLayout->setContentsMargins(5, 16, 5, 5); m_midiCCGroupBox->setLayout(knobsGroupBoxLayout); @@ -97,35 +97,35 @@ MidiCCRackView::MidiCCRackView( InstrumentTrack * track ) : QWidget *knobsArea = new QWidget(); QGridLayout *knobsAreaLayout = new QGridLayout(); - knobsArea->setLayout( knobsAreaLayout ); - knobsScrollArea->setWidget( knobsArea ); - knobsScrollArea->setWidgetResizable( true ); + knobsArea->setLayout(knobsAreaLayout); + knobsScrollArea->setWidget(knobsArea); + knobsScrollArea->setWidgetResizable(true); knobsGroupBoxLayout->addWidget(knobsScrollArea); // Adds the controller knobs - for(int i = 0; i < MidiControllerCount; i++){ - m_controllerKnob[i] = new Knob( knobBright_26 ); - m_controllerKnob[i]->setLabel( QString("CC %1").arg(QString::number(i)) ); - knobsAreaLayout->addWidget( m_controllerKnob[i], i/3, i%3 ); + for (int i = 0; i < MidiControllerCount; ++i){ + m_controllerKnob[i] = new Knob(knobBright_26); + m_controllerKnob[i]->setLabel(QString("CC %1").arg(QString::number(i))); + knobsAreaLayout->addWidget(m_controllerKnob[i], i/3, i%3); } // Set all the models // Set the LED button to enable/disable the track midi cc - m_midiCCGroupBox->setModel( m_track->m_midiCCEnable ); + m_midiCCGroupBox->setModel(m_track->m_midiCCEnable); // Set the model for each Knob - for( int i = 0; i < MidiControllerCount; ++i ){ - m_controllerKnob[i]->setModel( m_track->m_midiCCModel[i] ); + for (int i = 0; i < MidiControllerCount; ++i){ + m_controllerKnob[i]->setModel(m_track->m_midiCCModel[i]); } // Connection made to make sure the rack is destroyed if the track is destroyed - connect( m_track, SIGNAL( destroyedTrack() ), - this, SLOT( destroyRack() ) ); + connect(m_track, SIGNAL(destroyedTrack()), + this, SLOT(destroyRack())); // Connection to update the name of the track on the label - connect( m_track, SIGNAL( nameChanged() ), - this, SLOT( renameLabel() ) ); + connect(m_track, SIGNAL(nameChanged()), + this, SLOT(renameLabel())); // Adding everything to the main layout mainLayout->addWidget(trackToolBar); @@ -144,24 +144,23 @@ void MidiCCRackView::destroyRack() void MidiCCRackView::renameLabel() { - m_trackLabel->setText( QString( tr( "Track: %1" ) ).arg( m_track->name() ) ); + m_trackLabel->setText(QString(tr("Track: %1")).arg(m_track->name())); } void MidiCCRackView::unsetModels() { m_midiCCGroupBox->unsetModel(); - for( int i = 0; i < MidiControllerCount; ++i ) + for (int i = 0; i < MidiControllerCount; ++i) { m_controllerKnob[i]->unsetModel(); } } -void MidiCCRackView::saveSettings( QDomDocument & _doc, - QDomElement & _this ) +void MidiCCRackView::saveSettings(QDomDocument & doc, QDomElement & parent) { } -void MidiCCRackView::loadSettings( const QDomElement & _this ) +void MidiCCRackView::loadSettings(const QDomElement &) { } diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index e4230d2420d..772e92d5a3e 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -124,15 +124,15 @@ InstrumentTrack::InstrumentTrack( TrackContainer* tc ) : // Initialize the m_midiCCEnabled variable, but it's actually going to be connected // to a LedButton - m_midiCCEnable = new BoolModel( false, NULL, "Enable/Disable MIDI CC" ); + m_midiCCEnable = new BoolModel(false, nullptr, "Enable/Disable MIDI CC"); // Initialize the MIDI CC controller models and connect them to the method that processes // the midi cc events - for( int i = 0; i < MidiControllerCount; ++i ) + for (int i = 0; i < MidiControllerCount; ++i) { m_midiCCModel[i] = new FloatModel(0.0f, 0.0f, 127.0f, 1.0f, NULL, QString("CC Controller ") + QString::number(i)); - connect( m_midiCCModel[i], &FloatModel::dataChanged, - this, [this, i]{ processCCEvent(i); }, Qt::DirectConnection ); + connect(m_midiCCModel[i], &FloatModel::dataChanged, + this, [this, i]{ processCCEvent(i); }, Qt::DirectConnection); } setName( tr( "Default preset" ) ); @@ -162,7 +162,7 @@ InstrumentTrack::~InstrumentTrack() // Remove the MIDI CC models delete m_midiCCEnable; - for( int i = 0; i < MidiControllerCount; ++i ) + for (int i = 0; i < MidiControllerCount; ++i) { delete m_midiCCModel[i]; } @@ -269,18 +269,16 @@ MidiEvent InstrumentTrack::applyMasterKey( const MidiEvent& event ) void InstrumentTrack::processCCEvent(int controller) { // Does nothing if the LED is disabled - if( !m_midiCCEnable->value() ) - { - return; - } + if (!m_midiCCEnable->value()) { return; } - uint8_t channel = static_cast( midiPort()->realOutputChannel() ); - uint16_t cc = static_cast( controller ); - uint16_t value = static_cast( m_midiCCModel[ controller ]->value() ); + uint8_t channel = static_cast(midiPort()->realOutputChannel()); + uint16_t cc = static_cast(controller); + uint16_t value = static_cast(m_midiCCModel[controller]->value()); - // Process the MIDI CC event as an input event but with fromHardware set to false - // so we can know LMMS generated the event, not a controller. - processInEvent( MidiEvent( MidiControlChange, channel, cc, value, NULL, false ) ); + // Process the MIDI CC event as an input event but with ignoreOnExport set to false + // so we can know LMMS generated the event, not a controller, and can process it during + // the project export + processInEvent(MidiEvent(MidiControlChange, channel, cc, value, NULL, false)); } @@ -288,7 +286,7 @@ void InstrumentTrack::processCCEvent(int controller) void InstrumentTrack::processInEvent( const MidiEvent& event, const MidiTime& time, f_cnt_t offset ) { - if( Engine::getSong()->isExporting() && event.fromHardware() ) + if(Engine::getSong()->isExporting() && event.ignoreOnExport()) { return; } @@ -419,9 +417,9 @@ void InstrumentTrack::processInEvent( const MidiEvent& event, const MidiTime& ti // If the event wasn't handled, check if there's a loaded instrument and if so send the // event to it. If it returns false means the instrument didn't handle the event, so we trigger a warning. - if( eventHandled == false && !( instrument() && instrument()->handleMidiEvent( event, time, offset ) ) ) + if(eventHandled == false && !(instrument() && instrument()->handleMidiEvent(event, time, offset))) { - qWarning( "InstrumentTrack: unhandled MIDI event %d", event.type() ); + qWarning("InstrumentTrack: unhandled MIDI event %d", event.type()); } } @@ -796,12 +794,12 @@ void InstrumentTrack::saveTrackSpecificSettings( QDomDocument& doc, QDomElement m_useMasterPitchModel.saveSettings( doc, thisElement, "usemasterpitch"); // Save MIDI CC stuff - m_midiCCEnable->saveSettings( doc, thisElement, "enablecc" ); - QDomElement midiCC = doc.createElement( "midicontrollers" ); - thisElement.appendChild( midiCC ); - for( int i = 0; i < MidiControllerCount; ++i ) + m_midiCCEnable->saveSettings(doc, thisElement, "enablecc"); + QDomElement midiCC = doc.createElement("midicontrollers"); + thisElement.appendChild(midiCC); + for (int i = 0; i < MidiControllerCount; ++i) { - m_midiCCModel[i]->saveSettings( doc, midiCC, "cc" + QString::number(i) ); + m_midiCCModel[i]->saveSettings(doc, midiCC, "cc" + QString::number(i)); } if( m_instrument != NULL ) @@ -910,11 +908,11 @@ void InstrumentTrack::loadTrackSpecificSettings( const QDomElement & thisElement emit instrumentChanged(); } } - else if(node.nodeName() == "midicontrollers") + else if (node.nodeName() == "midicontrollers") { - for( int i = 0; i < MidiControllerCount; ++i ) + for (int i = 0; i < MidiControllerCount; ++i) { - m_midiCCModel[i]->loadSettings( node.toElement(), "cc" + QString::number(i) ); + m_midiCCModel[i]->loadSettings(node.toElement(), "cc" + QString::number(i)); } } // compat code - if node-name doesn't match any known @@ -939,7 +937,7 @@ void InstrumentTrack::loadTrackSpecificSettings( const QDomElement & thisElement } // Load the right value of m_midiCCEnable - m_midiCCEnable->loadSettings( thisElement, "enablecc" ); + m_midiCCEnable->loadSettings(thisElement, "enablecc"); updatePitchRange(); unlock(); @@ -1081,7 +1079,7 @@ InstrumentTrackView::InstrumentTrackView( InstrumentTrack * _it, TrackContainerV m_panningKnob->setLabel( tr( "PAN" ) ); m_panningKnob->show(); - m_midiCCRackView = new MidiCCRackView( _it ); + m_midiCCRackView = new MidiCCRackView(_it); m_midiMenu = new QMenu( tr( "MIDI" ), this ); @@ -1118,9 +1116,9 @@ InstrumentTrackView::InstrumentTrackView( InstrumentTrack * _it, TrackContainerV m_midiInputAction->setText( tr( "Input" ) ); m_midiOutputAction->setText( tr( "Output" ) ); - QAction *midiRackAction = m_midiMenu->addAction( "Open/Close MIDI CC Rack" ); - connect( midiRackAction, SIGNAL( triggered() ), - this, SLOT( toggleMidiCCRack() ) ); + QAction *midiRackAction = m_midiMenu->addAction("Open/Close MIDI CC Rack"); + connect(midiRackAction, SIGNAL(triggered()), + this, SLOT(toggleMidiCCRack())); m_activityIndicator = new FadeButton( QApplication::palette().color( QPalette::Active, QPalette::Background), @@ -1160,7 +1158,7 @@ InstrumentTrackView::~InstrumentTrackView() void InstrumentTrackView::toggleMidiCCRack() { - if( m_midiCCRackView->parentWidget()->isVisible() ) + if (m_midiCCRackView->parentWidget()->isVisible()) { m_midiCCRackView->parentWidget()->hide(); } From 19018c3ded877bdfbb5d6b9c7505f5577157134c Mon Sep 17 00:00:00 2001 From: Ian Caio Date: Mon, 16 Nov 2020 17:23:29 -0300 Subject: [PATCH 27/40] Remove unused signals Remove signals that were added to TrackContainer and TrackContainerView that aren't used anymore, since I changed the MIDI CC Rack to be individual per track. --- include/TrackContainer.h | 2 -- include/TrackContainerView.h | 1 - src/core/TrackContainer.cpp | 5 ----- src/gui/TrackContainerView.cpp | 2 -- 4 files changed, 10 deletions(-) diff --git a/include/TrackContainer.h b/include/TrackContainer.h index e89f0b20fab..fd853a73c1e 100644 --- a/include/TrackContainer.h +++ b/include/TrackContainer.h @@ -97,8 +97,6 @@ class LMMS_EXPORT TrackContainer : public Model, public JournallingObject signals: void trackAdded( Track * _track ); - void trackRemoved(); - void trackRenamed(); protected: static AutomatedValueMap automatedValuesFromTracks(const TrackList &tracks, MidiTime timeStart, int tcoNum = -1); diff --git a/include/TrackContainerView.h b/include/TrackContainerView.h index 4597fe17240..6e952189b01 100644 --- a/include/TrackContainerView.h +++ b/include/TrackContainerView.h @@ -183,7 +183,6 @@ public slots: signals: void positionChanged( const MidiTime & _pos ); - void movedTrackView(); } ; diff --git a/src/core/TrackContainer.cpp b/src/core/TrackContainer.cpp index 33be024c75f..95dd46f298c 100644 --- a/src/core/TrackContainer.cpp +++ b/src/core/TrackContainer.cpp @@ -181,9 +181,6 @@ void TrackContainer::addTrack( Track * _track ) m_tracksMutex.unlock(); _track->unlock(); emit trackAdded( _track ); - - connect(_track, SIGNAL(nameChanged()), - this, SIGNAL(trackRenamed())); } } @@ -210,8 +207,6 @@ void TrackContainer::removeTrack( Track * _track ) { Engine::getSong()->setModified(); } - - emit trackRemoved(); } } diff --git a/src/gui/TrackContainerView.cpp b/src/gui/TrackContainerView.cpp index 0d955b3443f..9b51c76f272 100644 --- a/src/gui/TrackContainerView.cpp +++ b/src/gui/TrackContainerView.cpp @@ -175,8 +175,6 @@ void TrackContainerView::moveTrackView( TrackView * trackView, int indexTo ) m_trackViews.move( indexFrom, indexTo ); realignTracks(); - - emit movedTrackView(); } From 23911d222487051dbc620050ce278fd9fe628649 Mon Sep 17 00:00:00 2001 From: Ian Caio Date: Mon, 16 Nov 2020 17:28:41 -0300 Subject: [PATCH 28/40] Randomizes MIDI CC rack position To avoid all MIDI CC racks being created on top of each other, and making the user confused because the bottom ones are overlapped, I'm now randomizing the X position between 50 and 780 and the Y position between 50 and 380. --- src/gui/widgets/MidiCCRackView.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/gui/widgets/MidiCCRackView.cpp b/src/gui/widgets/MidiCCRackView.cpp index 342a92c5271..fd8cc29faab 100644 --- a/src/gui/widgets/MidiCCRackView.cpp +++ b/src/gui/widgets/MidiCCRackView.cpp @@ -65,7 +65,10 @@ MidiCCRackView::MidiCCRackView(InstrumentTrack * track) : // Adjust window attributes, sizing and position subWin->setAttribute(Qt::WA_DeleteOnClose, false); - subWin->move(780, 50); + subWin->move( + rand() % 731 + 50, // X is choosen randomly from 50 to 780 + rand() % 331 + 50 // Y is choosen randomly from 50 to 380 + ); subWin->resize(350, 300); subWin->setFixedWidth(350); subWin->setMinimumHeight(300); From aba42c2711cfec7da33f587ba498c058151d5e2e Mon Sep 17 00:00:00 2001 From: Ian Caio Date: Mon, 23 Nov 2020 22:25:28 -0300 Subject: [PATCH 29/40] Fixes some code style issues This commit fixes some code style issues pointed out by Veratil's review. --- include/MidiEvent.h | 7 ++++--- src/gui/AutomatableModelView.cpp | 2 +- src/gui/widgets/MidiCCRackView.cpp | 6 ++++-- src/tracks/InstrumentTrack.cpp | 12 ++++++++---- 4 files changed, 17 insertions(+), 10 deletions(-) diff --git a/include/MidiEvent.h b/include/MidiEvent.h index 8e37fe23975..177ef75ea94 100644 --- a/include/MidiEvent.h +++ b/include/MidiEvent.h @@ -218,9 +218,10 @@ class MidiEvent const char* m_sysExData; const void* m_sourcePort; - bool m_ignoreOnExport; // Should we ignore this MIDI event when exporting a project? - // This helps us ignoring MIDI events that shouldn't be processed - // during a project export, like physical controller events. + + // This helps us ignore MIDI events that shouldn't be processed + // during a project export, like physical controller events. + bool m_ignoreOnExport; } ; #endif diff --git a/src/gui/AutomatableModelView.cpp b/src/gui/AutomatableModelView.cpp index 12dfe91c172..efd6967cf18 100644 --- a/src/gui/AutomatableModelView.cpp +++ b/src/gui/AutomatableModelView.cpp @@ -148,7 +148,7 @@ void AutomatableModelView::unsetModel() { if (dynamic_cast(this)) { - setModel(new FloatModel( 0, 0, 0, 1, nullptr, QString(), true)); + setModel(new FloatModel(0, 0, 0, 1, nullptr, QString(), true)); } else if (dynamic_cast(this)) { diff --git a/src/gui/widgets/MidiCCRackView.cpp b/src/gui/widgets/MidiCCRackView.cpp index fd8cc29faab..8ab0b3a6656 100644 --- a/src/gui/widgets/MidiCCRackView.cpp +++ b/src/gui/widgets/MidiCCRackView.cpp @@ -107,7 +107,8 @@ MidiCCRackView::MidiCCRackView(InstrumentTrack * track) : knobsGroupBoxLayout->addWidget(knobsScrollArea); // Adds the controller knobs - for (int i = 0; i < MidiControllerCount; ++i){ + for (int i = 0; i < MidiControllerCount; ++i) + { m_controllerKnob[i] = new Knob(knobBright_26); m_controllerKnob[i]->setLabel(QString("CC %1").arg(QString::number(i))); knobsAreaLayout->addWidget(m_controllerKnob[i], i/3, i%3); @@ -118,7 +119,8 @@ MidiCCRackView::MidiCCRackView(InstrumentTrack * track) : m_midiCCGroupBox->setModel(m_track->m_midiCCEnable); // Set the model for each Knob - for (int i = 0; i < MidiControllerCount; ++i){ + for (int i = 0; i < MidiControllerCount; ++i) + { m_controllerKnob[i]->setModel(m_track->m_midiCCModel[i]); } diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index 41ef088ea77..3a666f7a2aa 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -130,7 +130,11 @@ InstrumentTrack::InstrumentTrack( TrackContainer* tc ) : // the midi cc events for (int i = 0; i < MidiControllerCount; ++i) { - m_midiCCModel[i] = new FloatModel(0.0f, 0.0f, 127.0f, 1.0f, NULL, QString("CC Controller ") + QString::number(i)); + m_midiCCModel[i] = new FloatModel( + 0.0f, 0.0f, 127.0f, 1.0f, + nullptr, QString("CC Controller ") + QString::number(i) + ); + connect(m_midiCCModel[i], &FloatModel::dataChanged, this, [this, i]{ processCCEvent(i); }, Qt::DirectConnection); } @@ -286,7 +290,7 @@ void InstrumentTrack::processCCEvent(int controller) void InstrumentTrack::processInEvent( const MidiEvent& event, const MidiTime& time, f_cnt_t offset ) { - if(Engine::getSong()->isExporting() && event.ignoreOnExport()) + if (Engine::getSong()->isExporting() && event.ignoreOnExport()) { return; } @@ -417,7 +421,7 @@ void InstrumentTrack::processInEvent( const MidiEvent& event, const MidiTime& ti // If the event wasn't handled, check if there's a loaded instrument and if so send the // event to it. If it returns false means the instrument didn't handle the event, so we trigger a warning. - if(eventHandled == false && !(instrument() && instrument()->handleMidiEvent(event, time, offset))) + if (eventHandled == false && !(instrument() && instrument()->handleMidiEvent(event, time, offset))) { qWarning("InstrumentTrack: unhandled MIDI event %d", event.type()); } @@ -1065,7 +1069,7 @@ InstrumentTrackView::InstrumentTrackView( InstrumentTrack * _it, TrackContainerV m_panningKnob = new Knob( knobSmall_17, getTrackSettingsWidget(), tr( "Panning" ) ); m_panningKnob->setModel( &_it->m_panningModel ); - m_panningKnob->setHintText( tr( "Panning:" ), "%" ); + m_panningKnob->setHintText(tr("Panning:"), "%"); m_panningKnob->move( widgetWidth-24, 2 ); m_panningKnob->setLabel( tr( "PAN" ) ); m_panningKnob->show(); From d791b7eea694cfe70d383119bbd30be310ee9c58 Mon Sep 17 00:00:00 2001 From: Ian Caio Date: Sun, 29 Nov 2020 08:15:22 -0300 Subject: [PATCH 30/40] Moves MidiCCRackView.cpp to src/gui Moves source file to a more appropriate location. --- src/gui/CMakeLists.txt | 2 +- src/gui/{widgets => }/MidiCCRackView.cpp | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename src/gui/{widgets => }/MidiCCRackView.cpp (100%) diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index 80eb716031e..193c0b9012c 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -22,6 +22,7 @@ SET(LMMS_SRCS gui/Lv2ViewBase.cpp gui/MainApplication.cpp gui/MainWindow.cpp + gui/MidiCCRackView.cpp gui/MidiSetupWidget.cpp gui/ModelView.cpp gui/PeakControllerDialog.cpp @@ -78,7 +79,6 @@ SET(LMMS_SRCS gui/widgets/ControlLayout.cpp gui/widgets/LinkedModelGroupViews.cpp gui/widgets/MeterDialog.cpp - gui/widgets/MidiCCRackView.cpp gui/widgets/MidiPortMenu.cpp gui/widgets/NStateButton.cpp gui/widgets/Oscilloscope.cpp diff --git a/src/gui/widgets/MidiCCRackView.cpp b/src/gui/MidiCCRackView.cpp similarity index 100% rename from src/gui/widgets/MidiCCRackView.cpp rename to src/gui/MidiCCRackView.cpp From df71382959356f6fdb8cf5318360e4a42b1f6f43 Mon Sep 17 00:00:00 2001 From: Ian Caio Date: Sun, 29 Nov 2020 08:34:08 -0300 Subject: [PATCH 31/40] Removes track label and increases knobs per row Removes the label with the track name, moving the name of the track owning the MIDI CC rack to the window title. Makes it so we have 4 MIDI CC knobs per row, since the total number is not a multiple of 3 but a multiple of 4 (improves alignment). --- include/MidiCCRackView.h | 4 +--- src/gui/MidiCCRackView.cpp | 20 +++++--------------- 2 files changed, 6 insertions(+), 18 deletions(-) diff --git a/include/MidiCCRackView.h b/include/MidiCCRackView.h index de30c53089a..63e8f0f2364 100644 --- a/include/MidiCCRackView.h +++ b/include/MidiCCRackView.h @@ -34,11 +34,9 @@ class MidiCCRackView : public QWidget, public SerializingObject public slots: void unsetModels(); void destroyRack(); - void renameLabel(); + void renameWindow(); private: - QLabel *m_trackLabel; - InstrumentTrack *m_track; GroupBox *m_midiCCGroupBox; // MIDI CC GroupBox (used to enable disable MIDI CC) diff --git a/src/gui/MidiCCRackView.cpp b/src/gui/MidiCCRackView.cpp index 8ab0b3a6656..bd04621618e 100644 --- a/src/gui/MidiCCRackView.cpp +++ b/src/gui/MidiCCRackView.cpp @@ -54,7 +54,7 @@ MidiCCRackView::MidiCCRackView(InstrumentTrack * track) : m_track(track) { setWindowIcon(embed::getIconPixmap("midi_cc_rack")); - setWindowTitle(tr("MIDI CC Rack")); + setWindowTitle(tr("MIDI CC Rack - %1").arg(m_track->name())); QMdiSubWindow * subWin = gui->mainWindow()->addWindowedWidget(this); @@ -77,15 +77,6 @@ MidiCCRackView::MidiCCRackView(InstrumentTrack * track) : // Main window layout QVBoxLayout *mainLayout = new QVBoxLayout(this); - // Track name label layout - // We use a widget to be able to make this layout have a fixed height - QWidget *trackToolBar = new QWidget(); - QHBoxLayout *trackToolBarLayout = new QHBoxLayout(trackToolBar); - m_trackLabel = new QLabel(QString(tr("Track: %1")).arg(m_track->name())); - - trackToolBarLayout->addWidget(m_trackLabel); - trackToolBar->setFixedHeight(40); - // Knobs GroupBox - Here we have the MIDI CC controller knobs for the selected track m_midiCCGroupBox = new GroupBox(tr("MIDI CC Knobs:")); @@ -111,7 +102,7 @@ MidiCCRackView::MidiCCRackView(InstrumentTrack * track) : { m_controllerKnob[i] = new Knob(knobBright_26); m_controllerKnob[i]->setLabel(QString("CC %1").arg(QString::number(i))); - knobsAreaLayout->addWidget(m_controllerKnob[i], i/3, i%3); + knobsAreaLayout->addWidget(m_controllerKnob[i], i/4, i%4); } // Set all the models @@ -130,10 +121,9 @@ MidiCCRackView::MidiCCRackView(InstrumentTrack * track) : // Connection to update the name of the track on the label connect(m_track, SIGNAL(nameChanged()), - this, SLOT(renameLabel())); + this, SLOT(renameWindow())); // Adding everything to the main layout - mainLayout->addWidget(trackToolBar); mainLayout->addWidget(m_midiCCGroupBox); } @@ -147,9 +137,9 @@ void MidiCCRackView::destroyRack() parentWidget()->close(); } -void MidiCCRackView::renameLabel() +void MidiCCRackView::renameWindow() { - m_trackLabel->setText(QString(tr("Track: %1")).arg(m_track->name())); + setWindowTitle(tr("MIDI CC Rack - %1").arg(m_track->name())); } void MidiCCRackView::unsetModels() From 7d78af80934b82c806bd7499423642186a44f7f4 Mon Sep 17 00:00:00 2001 From: Ian Caio Date: Sun, 29 Nov 2020 09:00:24 -0300 Subject: [PATCH 32/40] Adds tr and remove unnecessary QString conversions Adds translation calls on the places that were lacking them and removes some unnecessary QString conversions. --- src/gui/MidiCCRackView.cpp | 2 +- src/tracks/InstrumentTrack.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/gui/MidiCCRackView.cpp b/src/gui/MidiCCRackView.cpp index bd04621618e..f0af09de9b1 100644 --- a/src/gui/MidiCCRackView.cpp +++ b/src/gui/MidiCCRackView.cpp @@ -101,7 +101,7 @@ MidiCCRackView::MidiCCRackView(InstrumentTrack * track) : for (int i = 0; i < MidiControllerCount; ++i) { m_controllerKnob[i] = new Knob(knobBright_26); - m_controllerKnob[i]->setLabel(QString("CC %1").arg(QString::number(i))); + m_controllerKnob[i]->setLabel(tr("CC %1").arg(i)); knobsAreaLayout->addWidget(m_controllerKnob[i], i/4, i%4); } diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index 76cc8b51138..9b9f5bf6c2a 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -124,7 +124,7 @@ InstrumentTrack::InstrumentTrack( TrackContainer* tc ) : // Initialize the m_midiCCEnabled variable, but it's actually going to be connected // to a LedButton - m_midiCCEnable = new BoolModel(false, nullptr, "Enable/Disable MIDI CC"); + m_midiCCEnable = new BoolModel(false, nullptr, tr("Enable/Disable MIDI CC")); // Initialize the MIDI CC controller models and connect them to the method that processes // the midi cc events @@ -132,7 +132,7 @@ InstrumentTrack::InstrumentTrack( TrackContainer* tc ) : { m_midiCCModel[i] = new FloatModel( 0.0f, 0.0f, 127.0f, 1.0f, - nullptr, QString("CC Controller ") + QString::number(i) + nullptr, tr("CC Controller %1").arg(i) ); connect(m_midiCCModel[i], &FloatModel::dataChanged, @@ -1111,7 +1111,7 @@ InstrumentTrackView::InstrumentTrackView( InstrumentTrack * _it, TrackContainerV m_midiInputAction->setText( tr( "Input" ) ); m_midiOutputAction->setText( tr( "Output" ) ); - QAction *midiRackAction = m_midiMenu->addAction("Open/Close MIDI CC Rack"); + QAction *midiRackAction = m_midiMenu->addAction(tr("Open/Close MIDI CC Rack")); connect(midiRackAction, SIGNAL(triggered()), this, SLOT(toggleMidiCCRack())); From c928f97492f06fa8e4462a82cea03e815d4301ce Mon Sep 17 00:00:00 2001 From: Ian Caio Date: Sun, 29 Nov 2020 10:35:32 -0300 Subject: [PATCH 33/40] Uses std::unique_ptr for the MIDI CC models Changes the MIDI CC models so they are private members of the InstrumentTrack class (makes MidiCCRackView a friend class so it can access them without the need of using setters/getters). Changes the MIDI CC model pointers to be std::unique_ptr, so we can move away from the responsability of freeing their allocations on the destructor. --- include/InstrumentTrack.h | 6 +++--- src/gui/MidiCCRackView.cpp | 4 ++-- src/tracks/InstrumentTrack.cpp | 22 +++++++++------------- 3 files changed, 14 insertions(+), 18 deletions(-) diff --git a/include/InstrumentTrack.h b/include/InstrumentTrack.h index db5449a198a..16ce379d6eb 100644 --- a/include/InstrumentTrack.h +++ b/include/InstrumentTrack.h @@ -223,9 +223,6 @@ class LMMS_EXPORT InstrumentTrack : public Track, public MidiEventProcessor void autoAssignMidiDevice( bool ); - BoolModel *m_midiCCEnable; - FloatModel *m_midiCCModel[MidiControllerCount]; - signals: void instrumentChanged(); void midiNoteOn( const Note& ); @@ -294,11 +291,14 @@ protected slots: Piano m_piano; + std::unique_ptr m_midiCCEnable; + std::unique_ptr m_midiCCModel[MidiControllerCount]; friend class InstrumentTrackView; friend class InstrumentTrackWindow; friend class NotePlayHandle; friend class InstrumentMiscView; + friend class MidiCCRackView; } ; diff --git a/src/gui/MidiCCRackView.cpp b/src/gui/MidiCCRackView.cpp index f0af09de9b1..8b835484c68 100644 --- a/src/gui/MidiCCRackView.cpp +++ b/src/gui/MidiCCRackView.cpp @@ -107,12 +107,12 @@ MidiCCRackView::MidiCCRackView(InstrumentTrack * track) : // Set all the models // Set the LED button to enable/disable the track midi cc - m_midiCCGroupBox->setModel(m_track->m_midiCCEnable); + m_midiCCGroupBox->setModel(m_track->m_midiCCEnable.get()); // Set the model for each Knob for (int i = 0; i < MidiControllerCount; ++i) { - m_controllerKnob[i]->setModel(m_track->m_midiCCModel[i]); + m_controllerKnob[i]->setModel(m_track->m_midiCCModel[i].get()); } // Connection made to make sure the rack is destroyed if the track is destroyed diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index 9b9f5bf6c2a..1f4bf9a30e4 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -124,18 +124,22 @@ InstrumentTrack::InstrumentTrack( TrackContainer* tc ) : // Initialize the m_midiCCEnabled variable, but it's actually going to be connected // to a LedButton - m_midiCCEnable = new BoolModel(false, nullptr, tr("Enable/Disable MIDI CC")); + m_midiCCEnable = std::unique_ptr( + new BoolModel(false, nullptr, tr("Enable/Disable MIDI CC")) + ); // Initialize the MIDI CC controller models and connect them to the method that processes // the midi cc events for (int i = 0; i < MidiControllerCount; ++i) { - m_midiCCModel[i] = new FloatModel( - 0.0f, 0.0f, 127.0f, 1.0f, - nullptr, tr("CC Controller %1").arg(i) + m_midiCCModel[i] = std::unique_ptr( + new FloatModel( + 0.0f, 0.0f, 127.0f, 1.0f, + nullptr, tr("CC Controller %1").arg(i) + ) ); - connect(m_midiCCModel[i], &FloatModel::dataChanged, + connect(m_midiCCModel[i].get(), &FloatModel::dataChanged, this, [this, i]{ processCCEvent(i); }, Qt::DirectConnection); } @@ -163,14 +167,6 @@ int InstrumentTrack::baseNote() const InstrumentTrack::~InstrumentTrack() { - // Remove the MIDI CC models - delete m_midiCCEnable; - - for (int i = 0; i < MidiControllerCount; ++i) - { - delete m_midiCCModel[i]; - } - // De-assign midi device if (m_hasAutoMidiDev) { From aa6345b4ba344f270c299e30abdbf70882283d4d Mon Sep 17 00:00:00 2001 From: Ian Caio Date: Sun, 29 Nov 2020 11:49:11 -0300 Subject: [PATCH 34/40] Implements the MidiCCRackView destructor I wasn't properly destroying each MidiCCRackView when a track was removed, causing them to build up. This commit changes the m_midiCCRackView variable on the InstrumentTrackView class to be a std::unique_ptr (destroyed when out of scope) and added the appropriate code on the MidiCCRackView class destructor to remove the parent widget. destroyRack() method was removed (it wasn't doing its task appropriately before and is now unnecessary after the destructor was fixed) and also unsetModels() which wasn't necessary anymore. --- include/InstrumentTrack.h | 2 +- include/MidiCCRackView.h | 2 -- src/gui/MidiCCRackView.cpp | 25 +++++-------------------- src/tracks/InstrumentTrack.cpp | 2 +- 4 files changed, 7 insertions(+), 24 deletions(-) diff --git a/include/InstrumentTrack.h b/include/InstrumentTrack.h index 16ce379d6eb..1ba365a9740 100644 --- a/include/InstrumentTrack.h +++ b/include/InstrumentTrack.h @@ -374,7 +374,7 @@ private slots: QAction * m_midiInputAction; QAction * m_midiOutputAction; - MidiCCRackView * m_midiCCRackView; + std::unique_ptr m_midiCCRackView; QPoint m_lastPos; diff --git a/include/MidiCCRackView.h b/include/MidiCCRackView.h index 63e8f0f2364..02f6fb9483c 100644 --- a/include/MidiCCRackView.h +++ b/include/MidiCCRackView.h @@ -32,8 +32,6 @@ class MidiCCRackView : public QWidget, public SerializingObject } public slots: - void unsetModels(); - void destroyRack(); void renameWindow(); private: diff --git a/src/gui/MidiCCRackView.cpp b/src/gui/MidiCCRackView.cpp index 8b835484c68..3467dcfaefe 100644 --- a/src/gui/MidiCCRackView.cpp +++ b/src/gui/MidiCCRackView.cpp @@ -115,10 +115,6 @@ MidiCCRackView::MidiCCRackView(InstrumentTrack * track) : m_controllerKnob[i]->setModel(m_track->m_midiCCModel[i].get()); } - // Connection made to make sure the rack is destroyed if the track is destroyed - connect(m_track, SIGNAL(destroyedTrack()), - this, SLOT(destroyRack())); - // Connection to update the name of the track on the label connect(m_track, SIGNAL(nameChanged()), this, SLOT(renameWindow())); @@ -129,12 +125,11 @@ MidiCCRackView::MidiCCRackView(InstrumentTrack * track) : MidiCCRackView::~MidiCCRackView() { -} - -void MidiCCRackView::destroyRack() -{ - unsetModels(); - parentWidget()->close(); + if(parentWidget()) + { + parentWidget()->hide(); + parentWidget()->deleteLater(); + } } void MidiCCRackView::renameWindow() @@ -142,16 +137,6 @@ void MidiCCRackView::renameWindow() setWindowTitle(tr("MIDI CC Rack - %1").arg(m_track->name())); } -void MidiCCRackView::unsetModels() -{ - m_midiCCGroupBox->unsetModel(); - - for (int i = 0; i < MidiControllerCount; ++i) - { - m_controllerKnob[i]->unsetModel(); - } -} - void MidiCCRackView::saveSettings(QDomDocument & doc, QDomElement & parent) { } diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index 1f4bf9a30e4..df4ac330091 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -1070,7 +1070,7 @@ InstrumentTrackView::InstrumentTrackView( InstrumentTrack * _it, TrackContainerV m_panningKnob->setLabel( tr( "PAN" ) ); m_panningKnob->show(); - m_midiCCRackView = new MidiCCRackView(_it); + m_midiCCRackView = std::unique_ptr(new MidiCCRackView(_it)); m_midiMenu = new QMenu( tr( "MIDI" ), this ); From 2e2b7c07d0b48179d799c9303d8633285dfdc318 Mon Sep 17 00:00:00 2001 From: Ian Caio Date: Sun, 29 Nov 2020 12:28:08 -0300 Subject: [PATCH 35/40] Uses lazy creation on the MidiCCRackView This commit makes it so the MidiCCRackView isn't created on the InstrumentTrackView constructor, but instead is only created on the first time it's toggled. --- src/gui/MidiCCRackView.cpp | 4 ---- src/tracks/InstrumentTrack.cpp | 9 +++++++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/gui/MidiCCRackView.cpp b/src/gui/MidiCCRackView.cpp index 3467dcfaefe..97a7876c3f6 100644 --- a/src/gui/MidiCCRackView.cpp +++ b/src/gui/MidiCCRackView.cpp @@ -65,10 +65,6 @@ MidiCCRackView::MidiCCRackView(InstrumentTrack * track) : // Adjust window attributes, sizing and position subWin->setAttribute(Qt::WA_DeleteOnClose, false); - subWin->move( - rand() % 731 + 50, // X is choosen randomly from 50 to 780 - rand() % 331 + 50 // Y is choosen randomly from 50 to 380 - ); subWin->resize(350, 300); subWin->setFixedWidth(350); subWin->setMinimumHeight(300); diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index df4ac330091..6ecad529c1b 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -1070,8 +1070,6 @@ InstrumentTrackView::InstrumentTrackView( InstrumentTrack * _it, TrackContainerV m_panningKnob->setLabel( tr( "PAN" ) ); m_panningKnob->show(); - m_midiCCRackView = std::unique_ptr(new MidiCCRackView(_it)); - m_midiMenu = new QMenu( tr( "MIDI" ), this ); // sequenced MIDI? @@ -1149,6 +1147,13 @@ InstrumentTrackView::~InstrumentTrackView() void InstrumentTrackView::toggleMidiCCRack() { + // Lazy creation: midiCCRackView is only created when accessed the first time. + // this->model() returns pointer to the InstrumentTrack who owns this InstrumentTrackView. + if (!m_midiCCRackView) + { + m_midiCCRackView = std::unique_ptr(new MidiCCRackView(this->model())); + } + if (m_midiCCRackView->parentWidget()->isVisible()) { m_midiCCRackView->parentWidget()->hide(); From 9d1aab62fd47caacd75b93536c376057d25a5c87 Mon Sep 17 00:00:00 2001 From: Ian Caio Date: Mon, 30 Nov 2020 00:01:57 -0300 Subject: [PATCH 36/40] Changes access specifiers and destructor Changes the access specifiers of methods on the MidiCCRackView (renameWindow from public slot to private slot) and InstrumentTrack (processCCEvent from public slot to private method) and fixes the MidiCCRackView destructor keyword being used (from virtual to override). --- include/InstrumentTrack.h | 5 ++--- include/MidiCCRackView.h | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/include/InstrumentTrack.h b/include/InstrumentTrack.h index 7b8092c2cf1..94fb287f039 100644 --- a/include/InstrumentTrack.h +++ b/include/InstrumentTrack.h @@ -231,9 +231,6 @@ class LMMS_EXPORT InstrumentTrack : public Track, public MidiEventProcessor void newNote(); void endNote(); -public slots: - void processCCEvent(int controller); - protected: QString nodeName() const override { @@ -252,6 +249,8 @@ protected slots: private: + void processCCEvent(int controller); + MidiPort m_midiPort; NotePlayHandle* m_notes[NumKeys]; diff --git a/include/MidiCCRackView.h b/include/MidiCCRackView.h index 02f6fb9483c..ca6ff7e030c 100644 --- a/include/MidiCCRackView.h +++ b/include/MidiCCRackView.h @@ -21,7 +21,7 @@ class MidiCCRackView : public QWidget, public SerializingObject Q_OBJECT public: MidiCCRackView(InstrumentTrack * track); - virtual ~MidiCCRackView(); + ~MidiCCRackView() override; void saveSettings(QDomDocument & doc, QDomElement & parent) override; void loadSettings(const QDomElement &) override; @@ -31,7 +31,7 @@ class MidiCCRackView : public QWidget, public SerializingObject return "MidiCCRackView"; } -public slots: +private slots: void renameWindow(); private: From 6bc6d8b5593993f225b20a131275ed247ca9f209 Mon Sep 17 00:00:00 2001 From: Ian Caio Date: Mon, 30 Nov 2020 00:08:47 -0300 Subject: [PATCH 37/40] Changes MIDI CC Rack icon Changes the icon used on the MIDI CC rack window to the one created by @wujekbrezniew. --- data/themes/classic/midi_cc_rack.png | Bin 667 -> 554 bytes data/themes/default/midi_cc_rack.png | Bin 667 -> 554 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/data/themes/classic/midi_cc_rack.png b/data/themes/classic/midi_cc_rack.png index 6ec1dd2ee0a011bc95791c6265102e76f2593829..1fe8bb9cb2479575cc5ecbcc0e32fc2bfca58ad4 100644 GIT binary patch delta 529 zcmV+s0`C2r1*!y)B!2{RLP=Bz2nYy#2xN!=000SaNLh0L00Ace00AcfjlA&80000P zbVXQnQ*UN;cVTj60C#tHE@^ISb7Ns}WiD@WXPfRk8UO$Rr%6OXR5*>jlut{PQ51)t zE5canrjD37Cfw;knbtv=GETFNTIkJcm0?Ya6RnO;GoBE~!Y+3EdH5GL$KL?*pN@)#v0)OlPA9HLMr~;e76fh2K03T9H zwOq3b`~V)Ol-3UoMD0|o>OHkx?Nh(2cSFr^c5+2c>WKPQJ=t)|*?Lvo4i-m3ekjDZ zGpyY7=yInI!%RP`gX%@~eU8=C2aP&Qji4Fa3tXdq6ZU^m>(p<>i{EDUue1lN=TZ@h Tg~xLM015yANkvXXu0mjfmBR4s delta 642 zcmV-|0)73e1e*nrB!32COGiWi{{a60|De66lK=n!32;bRa{vGdY5)KUY5_)3$LRn7 z00(qQO+^Rf2MQ1h0+d_jmH+?(C`m*?R5;76l|5(_K@@<$w;Q<&7Yrt6l!?Jcf{{op ztW0Agf})L(N+XC^q_fe&CQU3XY|>fS_*Yq|q!1z&Dq3hIT7TF?vNtoEOVEJ9Aa}dZ zW)2Q;hJSr8tfk1z=@mrCO;}o&skI7XD(4nOs|2+m~h8GB8=dJ&6D+mC8bpwN&+H zmSw|04Y&ZLz<*nSEXy7Q*(NXx)LO09kci9y+amH#8jZ$*D2l!VF>uQmbGv&<=iG#< zj*G}P@G_+5{OIWDi*C+)f41FjCs=E5IOo(kx7BPm2a1yIoO>9!&%F*MilS&5Ktw)_ zjErpcV5h@-xu;N7kA`@)2nt_*u#5wUfT0kt7eTF7YkyByiEWe#Ya!8_g~ci|(3PW~ zWx{q4R*Rr4%i3KH&|fC(97Mecs#dF8UBclqVWUh~uh-XsKV@7;_%-Bdsz(mnz_&1* zDl3~#U5z{ECVH?P?o^tlwL)Q@=g)v&fT-&Hzd({CL)O}P;1Qs}V4mmK|Ijlut{PQ51)t zE5canrjD37Cfw;knbtv=GETFNTIkJcm0?Ya6RnO;GoBE~!Y+3EdH5GL$KL?*pN@)#v0)OlPA9HLMr~;e76fh2K03T9H zwOq3b`~V)Ol-3UoMD0|o>OHkx?Nh(2cSFr^c5+2c>WKPQJ=t)|*?Lvo4i-m3ekjDZ zGpyY7=yInI!%RP`gX%@~eU8=C2aP&Qji4Fa3tXdq6ZU^m>(p<>i{EDUue1lN=TZ@h Tg~xLM015yANkvXXu0mjfmBR4s delta 642 zcmV-|0)73e1e*nrB!32COGiWi{{a60|De66lK=n!32;bRa{vGdY5)KUY5_)3$LRn7 z00(qQO+^Rf2MQ1h0+d_jmH+?(C`m*?R5;76l|5(_K@@<$w;Q<&7Yrt6l!?Jcf{{op ztW0Agf})L(N+XC^q_fe&CQU3XY|>fS_*Yq|q!1z&Dq3hIT7TF?vNtoEOVEJ9Aa}dZ zW)2Q;hJSr8tfk1z=@mrCO;}o&skI7XD(4nOs|2+m~h8GB8=dJ&6D+mC8bpwN&+H zmSw|04Y&ZLz<*nSEXy7Q*(NXx)LO09kci9y+amH#8jZ$*D2l!VF>uQmbGv&<=iG#< zj*G}P@G_+5{OIWDi*C+)f41FjCs=E5IOo(kx7BPm2a1yIoO>9!&%F*MilS&5Ktw)_ zjErpcV5h@-xu;N7kA`@)2nt_*u#5wUfT0kt7eTF7YkyByiEWe#Ya!8_g~ci|(3PW~ zWx{q4R*Rr4%i3KH&|fC(97Mecs#dF8UBclqVWUh~uh-XsKV@7;_%-Bdsz(mnz_&1* zDl3~#U5z{ECVH?P?o^tlwL)Q@=g)v&fT-&Hzd({CL)O}P;1Qs}V4mmK|I Date: Mon, 30 Nov 2020 00:13:47 -0300 Subject: [PATCH 38/40] Uses the MIDI CC icon on the menu action too --- src/tracks/InstrumentTrack.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index 0c27e8665e4..2732a34a68e 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -1106,6 +1106,7 @@ InstrumentTrackView::InstrumentTrackView( InstrumentTrack * _it, TrackContainerV m_midiOutputAction->setText( tr( "Output" ) ); QAction *midiRackAction = m_midiMenu->addAction(tr("Open/Close MIDI CC Rack")); + midiRackAction->setIcon(embed::getIconPixmap("midi_cc_rack")); connect(midiRackAction, SIGNAL(triggered()), this, SLOT(toggleMidiCCRack())); From 4a4cead6c80220863b8052069d1f3cb5a9143e43 Mon Sep 17 00:00:00 2001 From: Ian Caio Date: Mon, 30 Nov 2020 00:30:50 -0300 Subject: [PATCH 39/40] Reorganizes included headers Removes headers that weren't used anymore and organizes the remaining ones to conform to the code style. --- include/InstrumentTrack.h | 4 ++-- include/MidiCCRackView.h | 10 ++-------- src/gui/MidiCCRackView.cpp | 25 ++++++++----------------- 3 files changed, 12 insertions(+), 27 deletions(-) diff --git a/include/InstrumentTrack.h b/include/InstrumentTrack.h index 94fb287f039..aea007fec65 100644 --- a/include/InstrumentTrack.h +++ b/include/InstrumentTrack.h @@ -30,6 +30,8 @@ #include "GroupBox.h" #include "InstrumentFunctions.h" #include "InstrumentSoundShaping.h" +#include "Midi.h" +#include "MidiCCRackView.h" #include "MidiEventProcessor.h" #include "MidiPort.h" #include "NotePlayHandle.h" @@ -38,8 +40,6 @@ #include "Pitch.h" #include "Plugin.h" #include "Track.h" -#include "Midi.h" -#include "MidiCCRackView.h" diff --git a/include/MidiCCRackView.h b/include/MidiCCRackView.h index ca6ff7e030c..9d015e4e8fb 100644 --- a/include/MidiCCRackView.h +++ b/include/MidiCCRackView.h @@ -2,17 +2,11 @@ #define MIDI_CC_RACK_VIEW_H #include -#include -#include -#include "SerializingObject.h" -#include "lmms_basics.h" -#include "ComboBox.h" -#include "ComboBoxModel.h" -#include "Knob.h" -#include "TrackContainer.h" #include "GroupBox.h" +#include "Knob.h" #include "Midi.h" +#include "SerializingObject.h" class InstrumentTrack; diff --git a/src/gui/MidiCCRackView.cpp b/src/gui/MidiCCRackView.cpp index 97a7876c3f6..4d932fd1c5d 100644 --- a/src/gui/MidiCCRackView.cpp +++ b/src/gui/MidiCCRackView.cpp @@ -23,30 +23,21 @@ */ -#include -#include -#include -#include +#include "MidiCCRackView.h" + #include -#include +#include #include +#include +#include -#include "MidiCCRackView.h" -#include "GuiApplication.h" -#include "MainWindow.h" #include "embed.h" -#include "ComboBox.h" -#include "ComboBoxModel.h" #include "GroupBox.h" +#include "GuiApplication.h" +#include "InstrumentTrack.h" #include "Knob.h" +#include "MainWindow.h" #include "Track.h" -#include "InstrumentTrack.h" -#include "TrackContainer.h" -#include "BBTrackContainer.h" -#include "Engine.h" -#include "Song.h" -#include "SongEditor.h" -#include "BBEditor.h" MidiCCRackView::MidiCCRackView(InstrumentTrack * track) : From 291ebc431e83be504fc7bd7e99f5e662414a874b Mon Sep 17 00:00:00 2001 From: Ian Caio Date: Mon, 30 Nov 2020 08:56:42 -0300 Subject: [PATCH 40/40] Changes code to use std::make_unique Instead of using the std::unique_ptr constructor with the new allocator, we are now using C++14 std::make_unique when creating the unique pointers to the MIDI CC models. --- src/tracks/InstrumentTrack.cpp | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index 2732a34a68e..9057c9e1214 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -124,20 +124,14 @@ InstrumentTrack::InstrumentTrack( TrackContainer* tc ) : // Initialize the m_midiCCEnabled variable, but it's actually going to be connected // to a LedButton - m_midiCCEnable = std::unique_ptr( - new BoolModel(false, nullptr, tr("Enable/Disable MIDI CC")) - ); + m_midiCCEnable = std::make_unique(false, nullptr, tr("Enable/Disable MIDI CC")); // Initialize the MIDI CC controller models and connect them to the method that processes // the midi cc events for (int i = 0; i < MidiControllerCount; ++i) { - m_midiCCModel[i] = std::unique_ptr( - new FloatModel( - 0.0f, 0.0f, 127.0f, 1.0f, - nullptr, tr("CC Controller %1").arg(i) - ) - ); + m_midiCCModel[i] = std::make_unique(0.0f, 0.0f, 127.0f, 1.0f, + nullptr, tr("CC Controller %1").arg(i)); connect(m_midiCCModel[i].get(), &FloatModel::dataChanged, this, [this, i]{ processCCEvent(i); }, Qt::DirectConnection);