MIDI Control Listener setup dialog

Adds GUI elements to the global setup dialog to configure remote
controlling of LMMS via MIDI. The GUI is not yet fully functional,
though.

Signed-off-by: Tobias Doerffel <tobias.doerffel@gmail.com>
This commit is contained in:
Achim Settelmeier
2009-05-25 00:50:51 +02:00
committed by Tobias Doerffel
parent 57d4024c2a
commit 8d5b2c4813
4 changed files with 514 additions and 7 deletions

View File

@@ -32,15 +32,18 @@
#include "lmmsconfig.h"
#include "audio_device.h"
#include "midi_client.h"
#include "midi_control_listener.h"
class QComboBox;
class QLabel;
class QLineEdit;
class QSlider;
class QTableWidget;
class tabBar;
class groupBox;
class setupDialogMCL;
class setupDialog : public QDialog
{
@@ -57,7 +60,11 @@ public:
setupDialog( ConfigTabs _tab_to_open = GeneralSettings );
virtual ~setupDialog();
void mclAddKeyAction( int _key,
MidiControlListener::EventAction _action );
void mclAddControllerAction( int _controller,
MidiControlListener::EventAction _action );
protected slots:
virtual void accept( void );
@@ -106,8 +113,16 @@ private slots:
void toggleDisableChActInd( bool _disabled );
void toggleManualChPiano( bool _enabled );
void toggleMCLEnabled( bool _enabled );
void toggleMCLControlKey( bool _enabled );
void mclNewAction( void );
void mclDelAction( void );
private:
groupBox * setupMidiControlListener( QWidget * midi );
void mclUpdateActionTable( void );
tabBar * m_tabBar;
QSlider * m_bufSizeSlider;
@@ -162,7 +177,14 @@ private:
mswMap m_midiIfaceSetupWidgets;
trMap m_midiIfaceNames;
bool m_mclEnabled;
int m_mclChannel;
bool m_mclUseControlKey;
MidiControlListener::ActionMap m_mclActionMapKeys;
MidiControlListener::ActionMap m_mclActionMapControllers;
QList< QPair <char, int> > m_mclActionTableMap;
QTableWidget * m_mclActionTable;
} ;

View File

@@ -0,0 +1,61 @@
/*
* setup_dialog_mcl.h - dialog for setting up MIDI Control Listener
*
* Copyright (c) 2009 Achim Settelmeier <lmms/at/m1.sirlab.de>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program (see COPYING); if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
*/
#ifndef _SETUP_DIALOG_MCL_H
#define _SETUP_DIALOG_MCL_H
#include <QtGui/QDialog>
class setupDialog;
class setupDialogMCL : public QDialog
{
Q_OBJECT
public:
setupDialogMCL( setupDialog * _parent );
virtual ~setupDialogMCL( void );
protected slots:
virtual void accept( void );
private slots:
void clickedKeyBox( void );
void clickedControllerBox( void );
private:
setupDialog * m_parent;
bool m_keysActive; // true: configure key, false: configure controller
groupBox * m_actionKey_gb;
groupBox * m_actionController_gb;
QComboBox * m_actionsKey_box;
QComboBox * m_actionsController_box;
lcdSpinBoxModel * m_controllerSbModel;
} ;
#endif

View File

@@ -34,6 +34,9 @@
#include <QtGui/QMessageBox>
#include <QtGui/QSlider>
#include <QtGui/QWhatsThis>
#include <QtGui/QToolButton>
#include <QtGui/QTableWidget>
#include <QtGui/QHeaderView>
#include "setup_dialog.h"
@@ -49,7 +52,10 @@
#include "debug.h"
#include "tooltip.h"
#include "led_checkbox.h"
#include "group_box.h"
#include "lcd_spinbox.h"
#include "midi_control_listener.h"
#include "setup_dialog_mcl.h"
// platform-specific audio-interface-classes
@@ -114,7 +120,12 @@ setupDialog::setupDialog( ConfigTabs _tab_to_open ) :
m_disableChActInd( configManager::inst()->value( "ui",
"disablechannelactivityindicators" ).toInt() ),
m_manualChPiano( configManager::inst()->value( "ui",
"manualchannelpiano" ).toInt() )
"manualchannelpiano" ).toInt() ),
m_mclEnabled( engine::getMidiControlListener()->getEnabled() ),
m_mclChannel( engine::getMidiControlListener()->getChannel() ),
m_mclUseControlKey( engine::getMidiControlListener()->getUseControlKey() ),
m_mclActionMapKeys( engine::getMidiControlListener()->getActionMapKeys() ),
m_mclActionMapControllers( engine::getMidiControlListener()->getActionMapControllers() )
{
setWindowIcon( embed::getIconPixmap( "setup_general" ) );
setWindowTitle( tr( "Setup LMMS" ) );
@@ -637,13 +648,15 @@ setupDialog::setupDialog( ConfigTabs _tab_to_open ) :
connect( m_midiInterfaces, SIGNAL( activated( const QString & ) ),
this, SLOT( midiInterfaceChanged( const QString & ) ) );
groupBox * midicl_gb = setupMidiControlListener( midi );
midi_layout->addWidget( midiiface_tw );
midi_layout->addSpacing( 20 );
midi_layout->addWidget( msw );
midi_layout->addSpacing( 20 );
midi_layout->addWidget( midicl_gb );
midi_layout->addStretch();
m_tabBar->addTab( general, tr( "General settings" ), 0, FALSE, TRUE
)->setIcon( embed::getIconPixmap( "setup_general" ) );
m_tabBar->addTab( paths, tr( "Paths" ), 1, FALSE, TRUE
@@ -709,6 +722,141 @@ setupDialog::~setupDialog()
groupBox * setupDialog::setupMidiControlListener( QWidget * midi )
{
// MIDI control listener
groupBox * gb = new groupBox( tr( "MIDI REMOTE CONTROL" ),
midi );
gb->setFixedHeight( 235 );
gb->ledButton()->setChecked( m_mclEnabled );
connect( gb->ledButton(), SIGNAL( toggled( bool ) ),
this, SLOT( toggleMCLEnabled( bool ) ) );
// channel
lcdSpinBoxModel * channelSbModel = new lcdSpinBoxModel( /* this */ );
channelSbModel->setRange( 0, 16 );
channelSbModel->setStep( 1 );
channelSbModel->setValue( m_mclChannel + 1 );
lcdSpinBox * channelSb = new lcdSpinBox( 3, gb );
channelSb->setModel( channelSbModel );
channelSb->addTextForValue( 0, "---" );
channelSb->setLabel( tr( "CHANNEL" ) );
channelSb->move( 20, 20 );
// device
QToolButton * devicesBtn = new QToolButton( gb );
devicesBtn->setText( tr( "MIDI-device to receive "
"remote control events from" ) );
devicesBtn->setIcon( embed::getIconPixmap( "piano" ) );
devicesBtn->setGeometry( 100, 20, 32, 32 );
devicesBtn->setPopupMode( QToolButton::InstantPopup );
// use control key
ledCheckBox * controlKeyCb = new ledCheckBox(
tr( "Use control key" ),
gb );
controlKeyCb->move( 20, 60 );
controlKeyCb->setChecked( m_mclUseControlKey );
connect( controlKeyCb, SIGNAL( toggled( bool ) ),
this, SLOT( toggleMCLControlKey( bool ) ) );
m_mclActionTable = new QTableWidget( gb );
mclUpdateActionTable();
QWidget * buttons = new QWidget( gb );
QVBoxLayout * btn_layout = new QVBoxLayout( buttons );
btn_layout->setSpacing( 0 );
btn_layout->setMargin( 0 );
QPushButton * new_btn = new QPushButton( tr( "New" ), buttons );
connect( new_btn, SIGNAL( clicked() ), this, SLOT( mclNewAction() ) );
QPushButton * del_btn = new QPushButton( tr( "Del" ), buttons );
connect( del_btn, SIGNAL( clicked() ), this, SLOT( mclDelAction() ) );
btn_layout->addWidget( new_btn );
btn_layout->addSpacing( 5 );
btn_layout->addWidget( del_btn );
btn_layout->addStretch();
buttons->move( 275, 80 );
return gb;
}
void setupDialog::mclUpdateActionTable( void )
{
m_mclActionTableMap.clear();
QTableWidget * table = m_mclActionTable;
table->setColumnCount( 2 );
table->setRowCount( m_mclActionMapKeys.count() +
m_mclActionMapControllers.count() );
table->setGeometry(20, 80, 250, 145 );
QStringList headers;
headers << "Key/Ctrl" << "Action";
table->setHorizontalHeaderLabels( headers );
int row = 0;
QString key2NameMap[] =
{
"C", "C#", "D", "D#", "E", "F",
"F#", "G", "G#", "A", "A#", "B"
};
for( MidiControlListener::ActionMap::const_iterator it = m_mclActionMapKeys.begin();
it != m_mclActionMapKeys.end(); ++it, ++row )
{
int keyNr = it.key();
QString key = "Key ";
key += key2NameMap[ keyNr % 12 ];
key += QString::number( int( keyNr / 12 ) );
QTableWidgetItem * item = new QTableWidgetItem( key );
item->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled );
table->setItem( row, 0, item );
QString actionName = MidiControlListener::action2ActionNameMap( it.value() ).name;
item = new QTableWidgetItem( actionName );
item->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled );
table->setItem( row, 1, item );
table->setRowHeight( row, 20 );
m_mclActionTableMap.append( qMakePair( 'k', keyNr ) );
}
for( MidiControlListener::ActionMap::const_iterator it = m_mclActionMapControllers.begin();
it != m_mclActionMapControllers.end(); ++it, ++row )
{
QString controller = "Controller #";
controller += QString::number( it.key() );
QTableWidgetItem * item = new QTableWidgetItem( controller );
item->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled );
table->setItem( row, 0, item );
QString actionName = MidiControlListener::action2ActionNameMap( it.value() ).name;
item = new QTableWidgetItem( actionName );
item->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled );
table->setItem( row, 1, item );
table->setRowHeight( row, 20 );
m_mclActionTableMap.append( qMakePair( 'c', it.key() ) );
}
//table->setColumnWidth( 0, 135 );
//table->setColumnWidth( 1, 135 );
table->setEnabled( true );
table->setShowGrid( false );
table->setSortingEnabled( false );
table->setSelectionBehavior( QTableWidget::SelectRows );
table->verticalHeader()->hide();
table->setAlternatingRowColors( true );
}
void setupDialog::accept( void )
{
configManager::inst()->setValue( "mixer", "framesperaudiobuffer",
@@ -758,6 +906,14 @@ void setupDialog::accept( void )
{
it.value()->saveSettings();
}
// MIDI control listener
MidiControlListener * listener = engine::getMidiControlListener();
listener->setEnabled( m_mclEnabled );
listener->setChannel( m_mclChannel );
listener->setUseControlKey( m_mclUseControlKey );
listener->setActionMapKeys( m_mclActionMapKeys );
listener->setActionMapControllers( m_mclActionMapControllers );
configManager::inst()->saveConfigFile();
@@ -1161,6 +1317,75 @@ void setupDialog::displayMIDIHelp( void )
void setupDialog::toggleMCLEnabled( bool _enabled )
{
m_mclEnabled = _enabled;
}
void setupDialog::toggleMCLControlKey( bool _enabled )
{
m_mclUseControlKey = _enabled;
}
void setupDialog::mclNewAction( void )
{
setupDialogMCL sdMcl( this );
sdMcl.exec();
}
void setupDialog::mclDelAction( void )
{
int row = m_mclActionTable->currentRow();
if( row < 0 )
{
return; // sanity check: no row selected
}
QPair<char, int> entry = m_mclActionTableMap[ row ];
if( entry.first == 'k' )
{
m_mclActionMapKeys.remove( entry.second );
}
else if( entry.first == 'c' )
{
m_mclActionMapControllers.remove( entry.second );
}
mclUpdateActionTable();
}
void setupDialog::mclAddKeyAction( int _key,
MidiControlListener::EventAction _action )
{
m_mclActionMapKeys[ _key ] = _action;
mclUpdateActionTable();
}
void setupDialog::mclAddControllerAction( int _controller,
MidiControlListener::EventAction _action )
{
m_mclActionMapControllers[ _controller ] = _action;
mclUpdateActionTable();
}
#include "moc_setup_dialog.cxx"

View File

@@ -0,0 +1,199 @@
#ifndef SINGLE_SOURCE_COMPILE
/*
* setup_dialog_mcl.cpp - dialog for setting up MIDI Control Listener
*
* Copyright (c) 2009 Achim Settelmeier <lmms/at/m1.sirlab.de>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program (see COPYING); if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
*/
#include <QtGui/QLayout>
#include <QtGui/QPushButton>
#include <QComboBox>
#include "embed.h"
#include "group_box.h"
#include "lcd_spinbox.h"
#include "setup_dialog.h"
#include "setup_dialog_mcl.h"
setupDialogMCL::setupDialogMCL( setupDialog * _parent ) :
m_parent( _parent ),
m_keysActive( true )
{
setWindowTitle( tr( "New action" ) );
setModal( true );
QWidget * buttons = new QWidget( this );
QHBoxLayout * btn_layout = new QHBoxLayout( buttons );
btn_layout->setSpacing( 0 );
btn_layout->setMargin( 0 );
QPushButton * ok_btn = new QPushButton( embed::getIconPixmap( "apply" ),
tr( "OK" ), buttons );
connect( ok_btn, SIGNAL( clicked() ), this, SLOT( accept() ) );
QPushButton * cancel_btn = new QPushButton( embed::getIconPixmap(
"cancel" ),
tr( "Cancel" ),
buttons );
connect( cancel_btn, SIGNAL( clicked() ), this, SLOT( reject() ) );
btn_layout->addStretch();
btn_layout->addSpacing( 10 );
btn_layout->addWidget( ok_btn );
btn_layout->addSpacing( 10 );
btn_layout->addWidget( cancel_btn );
btn_layout->addSpacing( 10 );
QWidget * settings = new QWidget( this );
settings->setGeometry( 10, 10, 180, 100 );
QVBoxLayout * vlayout = new QVBoxLayout( this );
vlayout->setSpacing( 0 );
vlayout->setMargin( 0 );
vlayout->addWidget( settings );
vlayout->addSpacing( 10 );
vlayout->addWidget( buttons );
vlayout->addSpacing( 10 );
vlayout->addStretch();
m_actionKey_gb = new groupBox( tr( "MIDI KEYBOARD" ),
settings );
m_actionKey_gb->setFixedHeight( 60 );
m_actionKey_gb->ledButton()->setChecked( m_keysActive );
connect( m_actionKey_gb->ledButton(), SIGNAL( clicked() ),
this, SLOT( clickedKeyBox( ) ) );
m_actionController_gb = new groupBox( tr( "MIDI CONTROLLER" ),
settings );
m_actionController_gb->setFixedHeight( 100 );
m_actionController_gb->ledButton()->setChecked( ! m_keysActive );
connect( m_actionController_gb->ledButton(), SIGNAL( clicked() ),
this, SLOT( clickedControllerBox( ) ) );
QVBoxLayout * settings_vl = new QVBoxLayout( settings );
settings_vl->setSpacing( 0 );
settings_vl->setMargin( 0 );
settings_vl->addWidget( m_actionController_gb );
settings_vl->addSpacing( 10 );
settings_vl->addWidget( m_actionKey_gb );
settings_vl->addSpacing( 10 );
settings_vl->addStretch();
m_actionsKey_box = new QComboBox( m_actionKey_gb );
m_actionsKey_box->setGeometry( 10, 20, 150, 22 );
for( int i = 0; i < MidiControlListener::numActions; ++i )
{
MidiControlListener::ActionNameMap action = MidiControlListener::action2ActionNameMap( (MidiControlListener::EventAction) i );
if( action.name != "" )
{
m_actionsKey_box->addItem( action.name );
}
}
m_actionsController_box = new QComboBox( m_actionController_gb );
m_actionsController_box->setGeometry( 10, 30, 150, 22 );
for( int i = 0; i < MidiControlListener::numActions; ++i )
{
MidiControlListener::ActionNameMap action = MidiControlListener::action2ActionNameMap( (MidiControlListener::EventAction) i );
if( action.name != "" &&
action.action != MidiControlListener::ActionControl )
{
m_actionsController_box->addItem( action.name );
}
}
m_controllerSbModel = new lcdSpinBoxModel( /* this */ );
m_controllerSbModel->setRange( 0, 127 );
m_controllerSbModel->setStep( 1 );
m_controllerSbModel->setValue( 63 );
lcdSpinBox * controllerSb = new lcdSpinBox( 3, m_actionController_gb );
controllerSb->setModel( m_controllerSbModel );
controllerSb->setLabel( tr( "CONTROLLER" ) );
controllerSb->move( 20, 60 );
show();
}
setupDialogMCL::~setupDialogMCL( void )
{
}
void setupDialogMCL::accept( void )
{
if( m_keysActive )
{
MidiControlListener::ActionNameMap action =
MidiControlListener::actionName2ActionNameMap(
m_actionsKey_box->currentText() );
m_parent->mclAddKeyAction( 40, action.action );
}
else
{
MidiControlListener::ActionNameMap action =
MidiControlListener::actionName2ActionNameMap(
m_actionsController_box->currentText() );
m_parent->mclAddControllerAction( m_controllerSbModel->value(),
action.action );
}
QDialog::accept();
}
void setupDialogMCL::clickedKeyBox( void )
{
m_keysActive = true;
m_actionKey_gb->ledButton()->setChecked( true );
m_actionController_gb->ledButton()->setChecked( false );
}
void setupDialogMCL::clickedControllerBox( void )
{
m_keysActive = false;
m_actionKey_gb->ledButton()->setChecked( false );
m_actionController_gb->ledButton()->setChecked( true );
}
#include "moc_setup_dialog_mcl.cxx"
#endif