diff --git a/include/ControllerConnectionDialog.h b/include/ControllerConnectionDialog.h index 6fb9d45d046..e126440f342 100644 --- a/include/ControllerConnectionDialog.h +++ b/include/ControllerConnectionDialog.h @@ -58,23 +58,35 @@ class ControllerConnectionDialog : public QDialog { Q_OBJECT public: - ControllerConnectionDialog( QWidget * _parent, - const AutomatableModel * _target_model ); + ControllerConnectionDialog(QWidget* _parent, + const AutomatableModel* _target_model); ~ControllerConnectionDialog() override; - Controller * chosenController() + Controller* chosenController() { return m_controller; } public slots: -// void setSelection( const effectKey & _selection ); - void selectController(); +// void setSelection(const effectKey & _selection); + + // TODO: Add and improve doxy for these events: + // And, better yet, improve function naming all together + + //! "MIDI CONTROLLER" LedCheckBox clicked/toggled event void midiToggled(); + + //! "Autodetect" LedCheckBox clicked/toggled event + void autoDetectToggled(); + + //! "USER CONTROLLER" LedCheckBox clicked/toggled event void userToggled(); + + //! "OK" button clicked event + void selectController(); + void userSelected(); - void autoDetectToggled(); - void enableAutoDetect( QAction * _a ); + void enableAutoDetect(QAction* _a); protected slots: @@ -82,27 +94,27 @@ protected slots: private: - // Midi - GroupBox * m_midiGroupBox; - LcdSpinBox * m_midiChannelSpinBox; - LcdSpinBox * m_midiControllerSpinBox; - LedCheckBox * m_midiAutoDetectCheckBox; - MidiPortMenu * m_readablePorts; + // Midi controller groupbox + GroupBox* m_midiGroupBox; + LcdSpinBox* m_midiChannelSpinBox; + LcdSpinBox* m_midiControllerSpinBox; + LedCheckBox* m_midiAutoDetectCheckBox; + MidiPortMenu* m_readablePorts; BoolModel m_midiAutoDetect; - // User - GroupBox * m_userGroupBox; - ComboBox * m_userController; + // User controller groupbox + GroupBox* m_userGroupBox; + ComboBox* m_userController; - // Mapping - TabWidget * m_mappingBox; - QLineEdit * m_mappingFunction; + // Mapping function + TabWidget* m_mappingBox; + QLineEdit* m_mappingFunction; - Controller * m_controller; - const AutomatableModel * m_targetModel; + Controller* m_controller; + const AutomatableModel* m_targetModel; // Temporary midiController - AutoDetectMidiController * m_midiController; + AutoDetectMidiController* m_midiController; } ; diff --git a/src/gui/modals/ControllerConnectionDialog.cpp b/src/gui/modals/ControllerConnectionDialog.cpp index c7bdd28b4c7..ca1fa3d8222 100644 --- a/src/gui/modals/ControllerConnectionDialog.cpp +++ b/src/gui/modals/ControllerConnectionDialog.cpp @@ -51,9 +51,9 @@ namespace lmms class AutoDetectMidiController : public MidiController { public: - AutoDetectMidiController( Model* parent ) : - MidiController( parent ), - m_detectedMidiChannel( 0 ), + AutoDetectMidiController(Model* parent) : + MidiController(parent), + m_detectedMidiChannel(0), m_detectedMidiController(NONE) { updateName(); @@ -63,14 +63,14 @@ class AutoDetectMidiController : public MidiController ~AutoDetectMidiController() override = default; - void processInEvent( const MidiEvent& event, const TimePos& time, f_cnt_t offset = 0 ) override + void processInEvent(const MidiEvent& event, const TimePos& time, f_cnt_t offset = 0) override { - if( event.type() == MidiControlChange && - ( m_midiPort.inputChannel() == 0 || m_midiPort.inputChannel() == event.channel() + 1 ) ) + if(event.type() == MidiControlChange + && (m_midiPort.inputChannel() == 0 || m_midiPort.inputChannel() == event.channel() + 1)) { m_detectedMidiChannel = event.channel() + 1; m_detectedMidiController = event.controllerNumber(); - m_detectedMidiPort = Engine::audioEngine()->midiClient()->sourcePortName( event ); + m_detectedMidiPort = Engine::audioEngine()->midiClient()->sourcePortName(event); emit valueChanged(); } @@ -79,12 +79,12 @@ class AutoDetectMidiController : public MidiController // Would be a nice copy ctor, but too hard to add copy ctor because // model has none. - MidiController* copyToMidiController( Model* parent ) + MidiController* copyToMidiController(Model* parent) { auto c = new MidiController(parent); - c->m_midiPort.setInputChannel( m_midiPort.inputChannel() ); - c->m_midiPort.setInputController( m_midiPort.inputController() ); - c->subscribeReadablePorts( m_midiPort.readablePorts() ); + c->m_midiPort.setInputChannel(m_midiPort.inputChannel()); + c->m_midiPort.setInputController(m_midiPort.inputController()); + c->subscribeReadablePorts(m_midiPort.readablePorts()); c->updateName(); return c; @@ -93,14 +93,13 @@ class AutoDetectMidiController : public MidiController void useDetected() { - m_midiPort.setInputChannel( m_detectedMidiChannel ); - m_midiPort.setInputController( m_detectedMidiController ); + m_midiPort.setInputChannel(m_detectedMidiChannel); + m_midiPort.setInputController(m_detectedMidiController); const MidiPort::Map& map = m_midiPort.readablePorts(); - for( MidiPort::Map::ConstIterator it = map.begin(); it != map.end(); ++it ) + for(MidiPort::Map::ConstIterator it = map.begin(); it != map.end(); ++it) { - m_midiPort.subscribeReadablePort( it.key(), - m_detectedMidiPort.isEmpty() || ( it.key() == m_detectedMidiPort ) ); + m_midiPort.subscribeReadablePort(it.key(), m_detectedMidiPort.isEmpty() || (it.key() == m_detectedMidiPort)); } } @@ -108,8 +107,8 @@ class AutoDetectMidiController : public MidiController public slots: void reset() { - m_midiPort.setInputChannel( 0 ); - m_midiPort.setInputController( 0 ); + m_midiPort.setInputChannel(0); + m_midiPort.setInputController(0); } @@ -125,136 +124,122 @@ public slots: namespace gui { -ControllerConnectionDialog::ControllerConnectionDialog( QWidget * _parent, - const AutomatableModel * _target_model ) : - QDialog( _parent ), - m_readablePorts( nullptr ), - m_midiAutoDetect( false ), - m_controller( nullptr ), - m_targetModel( _target_model ), - m_midiController( nullptr ) +ControllerConnectionDialog::ControllerConnectionDialog(QWidget* _parent, const AutomatableModel* _target_model) : + QDialog(_parent), + m_readablePorts(nullptr), + m_midiAutoDetect(false), + m_controller(nullptr), + m_targetModel(_target_model), + m_midiController(nullptr) { - setWindowIcon( embed::getIconPixmap( "setup_audio" ) ); - setWindowTitle( tr( "Connection Settings" ) ); - setModal( true ); - - // Midi stuff - m_midiGroupBox = new GroupBox( tr( "MIDI CONTROLLER" ), this ); - m_midiGroupBox->setGeometry( 8, 10, 240, 80 ); - connect( m_midiGroupBox->model(), SIGNAL(dataChanged()), - this, SLOT(midiToggled())); + setWindowIcon(embed::getIconPixmap("setup_audio")); + setWindowTitle(tr("Connection Settings")); + setModal(true); + + // Midi controller groupbox + m_midiGroupBox = new GroupBox(tr("MIDI CONTROLLER"), this); + m_midiGroupBox->setGeometry(8, 10, 240, 80); + connect(m_midiGroupBox->model(), SIGNAL(dataChanged()), this, SLOT(midiToggled())); - m_midiChannelSpinBox = new LcdSpinBox( 2, m_midiGroupBox, - tr( "Input channel" ) ); - m_midiChannelSpinBox->addTextForValue( 0, "--" ); - m_midiChannelSpinBox->setLabel( tr( "CHANNEL" ) ); - m_midiChannelSpinBox->move( 8, 24 ); - - m_midiControllerSpinBox = new LcdSpinBox( 3, m_midiGroupBox, - tr( "Input controller" ) ); - m_midiControllerSpinBox->addTextForValue(MidiController::NONE, "---" ); - m_midiControllerSpinBox->setLabel( tr( "CONTROLLER" ) ); - m_midiControllerSpinBox->move( 68, 24 ); + m_midiChannelSpinBox = new LcdSpinBox(2, m_midiGroupBox, tr("Input channel")); + m_midiChannelSpinBox->addTextForValue(0, "--"); + m_midiChannelSpinBox->setLabel(tr("CHANNEL")); + m_midiChannelSpinBox->move(8, 24); + + m_midiControllerSpinBox = new LcdSpinBox(3, m_midiGroupBox, tr("Input controller")); + m_midiControllerSpinBox->addTextForValue(MidiController::NONE, "---"); + m_midiControllerSpinBox->setLabel(tr("CONTROLLER")); + m_midiControllerSpinBox->move(68, 24); - - m_midiAutoDetectCheckBox = - new LedCheckBox( tr("Auto Detect"), - m_midiGroupBox, tr("Auto Detect") ); - m_midiAutoDetectCheckBox->setModel( &m_midiAutoDetect ); - m_midiAutoDetectCheckBox->move( 8, 60 ); - connect( &m_midiAutoDetect, SIGNAL(dataChanged()), - this, SLOT(autoDetectToggled())); - - // when using with non-raw-clients we can provide buttons showing - // our port-menus when being clicked - if( !Engine::audioEngine()->midiClient()->isRaw() ) + m_midiAutoDetectCheckBox = new LedCheckBox(tr("Auto Detect"), m_midiGroupBox, tr("Auto Detect")); + m_midiAutoDetectCheckBox->setModel(&m_midiAutoDetect); + m_midiAutoDetectCheckBox->move(8, 60); + connect(&m_midiAutoDetect, SIGNAL(dataChanged()), this, SLOT(autoDetectToggled())); + + // For non-raw clients, provide a button that displays a menu of MIDI input ports + // users can select from to enable auto-detection on chosen ports. + if(!Engine::audioEngine()->midiClient()->isRaw()) { - m_readablePorts = new MidiPortMenu( MidiPort::Mode::Input ); - connect( m_readablePorts, SIGNAL(triggered(QAction*)), - this, SLOT(enableAutoDetect(QAction*))); + m_readablePorts = new MidiPortMenu(MidiPort::Mode::Input); + connect(m_readablePorts, SIGNAL(triggered(QAction*)), this, SLOT(enableAutoDetect(QAction*))); + auto rp_btn = new ToolButton(m_midiGroupBox); - rp_btn->setText( tr( "MIDI-devices to receive " - "MIDI-events from" ) ); - rp_btn->setIcon( embed::getIconPixmap( "piano" ) ); - rp_btn->setGeometry( 160, 24, 32, 32 ); - rp_btn->setMenu( m_readablePorts ); - rp_btn->setPopupMode( QToolButton::InstantPopup ); + rp_btn->setText(tr("MIDI-devices to receive MIDI-events from")); + rp_btn->setIcon(embed::getIconPixmap("piano")); + rp_btn->setGeometry(160, 24, 32, 32); + rp_btn->setMenu(m_readablePorts); + rp_btn->setPopupMode(QToolButton::InstantPopup); } - // User stuff - m_userGroupBox = new GroupBox( tr( "USER CONTROLLER" ), this ); - m_userGroupBox->setGeometry( 8, 100, 240, 60 ); - connect( m_userGroupBox->model(), SIGNAL(dataChanged()), - this, SLOT(userToggled())); + // User controller groupbox + m_userGroupBox = new GroupBox(tr("USER CONTROLLER"), this); + m_userGroupBox->setGeometry(8, 100, 240, 60); + connect(m_userGroupBox->model(), SIGNAL(dataChanged()), this, SLOT(userToggled())); - m_userController = new ComboBox( m_userGroupBox, "Controller" ); - m_userController->setGeometry( 10, 24, 200, ComboBox::DEFAULT_HEIGHT ); - for (Controller * c : Engine::getSong()->controllers()) + m_userController = new ComboBox(m_userGroupBox, "Controller"); + m_userController->setGeometry(10, 24, 200, ComboBox::DEFAULT_HEIGHT); + for (Controller* c : Engine::getSong()->controllers()) { - m_userController->model()->addItem( c->name() ); + m_userController->model()->addItem(c->name()); } - connect( m_userController->model(), SIGNAL(dataUnchanged()), - this, SLOT(userSelected())); - connect( m_userController->model(), SIGNAL(dataChanged()), - this, SLOT(userSelected())); + connect(m_userController->model(), SIGNAL(dataUnchanged()), this, SLOT(userSelected())); + connect(m_userController->model(), SIGNAL(dataChanged()), this, SLOT(userSelected())); - // Mapping functions - m_mappingBox = new TabWidget( tr( "MAPPING FUNCTION" ), this ); - m_mappingBox->setGeometry( 8, 170, 240, 64 ); - m_mappingFunction = new QLineEdit( m_mappingBox ); - m_mappingFunction->setGeometry( 10, 20, 170, 16 ); - m_mappingFunction->setText( "input" ); - m_mappingFunction->setReadOnly( true ); + // Mapping function + m_mappingBox = new TabWidget(tr("MAPPING FUNCTION"), this); + m_mappingBox->setGeometry(8, 170, 240, 64); + m_mappingFunction = new QLineEdit(m_mappingBox); + m_mappingFunction->setGeometry(10, 20, 170, 16); + m_mappingFunction->setText("input"); + m_mappingFunction->setReadOnly(true); - // Buttons + // Buttons ("OK" and "Cancel" at the bottom) auto buttons = new QWidget(this); - buttons->setGeometry( 8, 240, 240, 32 ); + buttons->setGeometry(8, 240, 240, 32); auto btn_layout = new QHBoxLayout(buttons); - btn_layout->setSpacing( 0 ); + btn_layout->setSpacing(0); btn_layout->setContentsMargins(0, 0, 0, 0); auto select_btn = new QPushButton(embed::getIconPixmap("add"), tr("OK"), buttons); - connect( select_btn, SIGNAL(clicked()), - this, SLOT(selectController())); + connect(select_btn, SIGNAL(clicked()), this, SLOT(selectController())); auto cancel_btn = new QPushButton(embed::getIconPixmap("cancel"), tr("Cancel"), buttons); - connect( cancel_btn, SIGNAL(clicked()), - this, SLOT(reject())); + connect(cancel_btn, SIGNAL(clicked()), this, SLOT(reject())); btn_layout->addStretch(); - btn_layout->addSpacing( 10 ); - btn_layout->addWidget( select_btn ); - btn_layout->addSpacing( 10 ); - btn_layout->addWidget( cancel_btn ); - btn_layout->addSpacing( 10 ); + btn_layout->addSpacing(10); + btn_layout->addWidget(select_btn); + btn_layout->addSpacing(10); + btn_layout->addWidget(cancel_btn); + btn_layout->addSpacing(10); - setFixedSize( 256, 280 ); + setFixedSize(256, 280); // Crazy MIDI View stuff - // TODO, handle by making this a model for the Dialog "view" - ControllerConnection * cc = nullptr; - if( m_targetModel ) + // TODO: handle by making this a model for the Dialog "view" + ControllerConnection* cc = nullptr; + if(m_targetModel) { cc = m_targetModel->controllerConnection(); - - if( cc && cc->getController()->type() != Controller::ControllerType::Dummy && Engine::getSong() ) + if(cc && cc->getController()->type() != Controller::ControllerType::Dummy && Engine::getSong()) { - if ( cc->getController()->type() == Controller::ControllerType::Midi ) + if (cc->getController()->type() == Controller::ControllerType::Midi) { - m_midiGroupBox->model()->setValue( true ); - // ensure controller is created + m_midiGroupBox->model()->setValue(true); + // Ensure the controller is created by faking an interaction with the LedCheckBox for MIDI Controller: midiToggled(); auto cont = (MidiController*)(cc->getController()); - m_midiChannelSpinBox->model()->setValue( cont->m_midiPort.inputChannel() ); - m_midiControllerSpinBox->model()->setValue( cont->m_midiPort.inputController() ); + m_midiChannelSpinBox->model()->setValue(cont->m_midiPort.inputChannel()); + m_midiControllerSpinBox->model()->setValue(cont->m_midiPort.inputController()); - m_midiController->subscribeReadablePorts( static_cast( cc->getController() )->m_midiPort.readablePorts() ); + m_midiController->subscribeReadablePorts(static_cast + (cc->getController())->m_midiPort.readablePorts()); } else { @@ -264,17 +249,14 @@ ControllerConnectionDialog::ControllerConnectionDialog( QWidget * _parent, if (it != controllers.end()) { int idx = std::distance(controllers.begin(), it); - m_userGroupBox->model()->setValue( true ); - m_userController->model()->setValue( idx ); + m_userGroupBox->model()->setValue(true); + m_userController->model()->setValue(idx); } } } } - if( !cc ) - { - m_midiGroupBox->model()->setValue( true ); - } + if(!cc) { m_midiGroupBox->model()->setValue(true); } show(); } @@ -285,7 +267,6 @@ ControllerConnectionDialog::ControllerConnectionDialog( QWidget * _parent, ControllerConnectionDialog::~ControllerConnectionDialog() { delete m_readablePorts; - delete m_midiController; } @@ -294,40 +275,37 @@ ControllerConnectionDialog::~ControllerConnectionDialog() void ControllerConnectionDialog::selectController() { - // Midi + // Midi controller groupbox if (m_midiGroupBox->model()->value()) { - if( m_midiControllerSpinBox->model()->value() > 0 ) + if(m_midiControllerSpinBox->model()->value() > 0) { auto mc = m_midiController->copyToMidiController(Engine::getSong()); - - /* - if( m_targetModel->getTrack() && - !m_targetModel->getTrack()->displayName().isEmpty() ) + /*if(m_targetModel->getTrack() && + !m_targetModel->getTrack()->displayName().isEmpty()) { - mc->m_midiPort.setName( QString( "%1 (%2)" ). - arg( m_targetModel->getTrack()->displayName() ). - arg( m_targetModel->displayName() ) ); + mc->m_midiPort.setName(QString("%1 (%2)"). + arg(m_targetModel->getTrack()->displayName()). + arg(m_targetModel->displayName())); } else { - mc->m_midiPort.setName( m_targetModel->displayName() ); - } - */ - mc->m_midiPort.setName( m_targetModel->fullDisplayName() ); + mc->m_midiPort.setName(m_targetModel->displayName()); + }*/ + mc->m_midiPort.setName(m_targetModel->fullDisplayName()); m_controller = mc; } } - // User + + // User controller groupbox else { if (m_userGroupBox->model()->value() && Engine::getSong()->controllers().size()) { - m_controller = Engine::getSong()->controllers().at( - m_userController->model()->value() ); + m_controller = Engine::getSong()->controllers().at(m_userController->model()->value()); } - if( m_controller && m_controller->hasModel( m_targetModel ) ) + if(m_controller && m_controller->hasModel(m_targetModel)) { QMessageBox::warning(this, tr("LMMS"), tr("Cycle Detected.")); return; @@ -338,46 +316,44 @@ void ControllerConnectionDialog::selectController() accept(); } - - - void ControllerConnectionDialog::midiToggled() { int enabled = m_midiGroupBox->model()->value(); - if( enabled != 0 ) + if(enabled != 0) { - if( m_userGroupBox->model()->value() != 0 ) - { - m_userGroupBox->model()->setValue( 0 ); - } + if(m_userGroupBox->model()->value() != 0) { m_userGroupBox->model()->setValue(0); } - if( !m_midiController ) + if(!m_midiController) { - m_midiController = new AutoDetectMidiController( Engine::getSong() ); + m_midiController = new AutoDetectMidiController(Engine::getSong()); MidiPort::Map map = m_midiController->m_midiPort.readablePorts(); - for( MidiPort::Map::Iterator it = map.begin(); it != map.end(); ++it ) + for(MidiPort::Map::Iterator it = map.begin(); it != map.end(); ++it) { it.value() = true; } - m_midiController->subscribeReadablePorts( map ); + m_midiController->subscribeReadablePorts(map); - m_midiChannelSpinBox->setModel( &m_midiController->m_midiPort.m_inputChannelModel ); - m_midiControllerSpinBox->setModel( &m_midiController->m_midiPort.m_inputControllerModel ); + m_midiChannelSpinBox->setModel(&m_midiController->m_midiPort.m_inputChannelModel); + m_midiControllerSpinBox->setModel(&m_midiController->m_midiPort.m_inputControllerModel); - if( m_readablePorts ) + if(m_readablePorts) { - m_readablePorts->setModel( &m_midiController->m_midiPort ); + m_readablePorts->setModel(&m_midiController->m_midiPort); } - connect( m_midiController, SIGNAL(valueChanged()), this, SLOT(midiValueChanged())); + connect(m_midiController, SIGNAL(valueChanged()), this, SLOT(midiValueChanged())); } } - m_midiAutoDetect.setValue( enabled ); - m_midiChannelSpinBox->setEnabled( enabled ); - m_midiControllerSpinBox->setEnabled( enabled ); - m_midiAutoDetectCheckBox->setEnabled( enabled ); + // TODO: This should be reworked into some sort of "shadow" state rather than turning it off... + // since it makes for switching between the USER mode and CONTROLLER mode a bit awkward + // If you toggle the autodetect then move from MIDI to USER then back to MIDI it resets, which is not ideal. + m_midiAutoDetect.setValue(enabled && (!m_targetModel->controllerConnection())); + + m_midiChannelSpinBox->setEnabled(enabled); + m_midiControllerSpinBox->setEnabled(enabled); + m_midiAutoDetectCheckBox->setEnabled(enabled); } @@ -386,9 +362,9 @@ void ControllerConnectionDialog::midiToggled() void ControllerConnectionDialog::userToggled() { int enabled = m_userGroupBox->model()->value(); - if( enabled != 0 && m_midiGroupBox->model()->value() != 0 ) + if(enabled != 0 && m_midiGroupBox->model()->value() != 0) { - m_midiGroupBox->model()->setValue( 0 ); + m_midiGroupBox->model()->setValue(0); } } @@ -397,13 +373,14 @@ void ControllerConnectionDialog::userToggled() void ControllerConnectionDialog::userSelected() { - m_userGroupBox->model()->setValue( 1 ); + m_userGroupBox->model()->setValue(1); userToggled(); } - +// TODO: Suggestion (maybe this _should_ be an issue?), toggling Autodetect ON should NOT clear the controller, +// instead, the 'clear connection' button should be used; This prevents accidents, and makes UI clearer! void ControllerConnectionDialog::autoDetectToggled() { if (m_midiAutoDetect.value() && m_midiController) @@ -414,13 +391,13 @@ void ControllerConnectionDialog::autoDetectToggled() - void ControllerConnectionDialog::midiValueChanged() { - if( m_midiAutoDetect.value() ) + if(m_midiAutoDetect.value()) { m_midiController->useDetected(); - if( m_readablePorts ) + m_midiAutoDetect.setValue(false); + if(m_readablePorts) { m_readablePorts->updateMenu(); } @@ -429,11 +406,11 @@ void ControllerConnectionDialog::midiValueChanged() -void ControllerConnectionDialog::enableAutoDetect( QAction * _a ) +void ControllerConnectionDialog::enableAutoDetect(QAction* _a) { - if( _a->isChecked() ) + if(_a->isChecked()) { - m_midiAutoDetectCheckBox->model()->setValue( true ); + m_midiAutoDetectCheckBox->model()->setValue(true); } }