Add initial controller support for MIDI CC and various tweaks

git-svn-id: https://lmms.svn.sf.net/svnroot/lmms/trunk/lmms@1040 0778d3d1-df1d-0410-868b-ea421aaaa00d
This commit is contained in:
Paul Giblock
2008-06-02 05:02:09 +00:00
parent 1f42dadbd1
commit d188056683
16 changed files with 530 additions and 236 deletions

View File

@@ -1,3 +1,37 @@
2008-06-02 Paul Giblock <drfaygo/at/gmail/dot/com>
* include/controller_connection.h:
* src/core/automatable_model.cpp:
* src/core/controller_connection.cpp:
Support for automatic deletion of controller if owned by connection
* include/controller.h:
* include/midi_controller.h:
* include/controller_connection_dialog.h:
* src/gui/controller_connection_dialog.cpp:
* src/core/midi/midi_controller.cpp:
* src/core/controller.cpp:
* Makefile.am:
- Add midi-controller support
- Code clean-up
* include/midi.h:
add const for max controller ID and add bytes array to the midiEvent
m_data union
* src/core/midi/midi_client.cpp:
Don't subtract octave from control change events
* src/tracks/instrument_track.cpp:
Ignore unhandled control change events
* src/tracks/pattern.cpp:
Minor pixel adjustment to TCO drawing
* src/core/track.cpp:
Correct misleading textFloat
2008-06-01 Paul Giblock <drfaygo/at/gmail/dot/com>
* src/tracks/pattern.cpp:

View File

@@ -102,6 +102,7 @@ lmms_MOC = \
./nstate_button.moc \
./meter_model.moc \
./midi_alsa_seq.moc \
./midi_controller.moc \
./instrument_midi_io.moc \
./pattern.moc \
./piano_roll.moc \
@@ -230,6 +231,7 @@ lmms_SOURCES = \
$(srcdir)/src/core/midi/midi_alsa_raw.cpp \
$(srcdir)/src/core/midi/midi_alsa_seq.cpp \
$(srcdir)/src/core/midi/midi_client.cpp \
$(srcdir)/src/core/midi/midi_controller.cpp \
$(srcdir)/src/core/midi/midi_mapper.cpp \
$(srcdir)/src/core/midi/midi_oss.cpp \
$(srcdir)/src/core/midi/midi_port.cpp \
@@ -382,6 +384,7 @@ lmms_SOURCES = \
$(srcdir)/include/midi.h \
$(srcdir)/include/midi_alsa_raw.h \
$(srcdir)/include/midi_client.h \
$(srcdir)/include/midi_controller.h \
$(srcdir)/include/midi_event_processor.h \
$(srcdir)/include/midi_oss.h \
$(srcdir)/include/midi_port.h \

View File

@@ -47,14 +47,14 @@ class controller : public model, public journallingObject
public:
enum ControllerTypes
{
DummyController,
DummyController,
LfoController,
MidiController,
/*
MidiController,
XYController,
XYController,
PeakController,
*/
NumControllerTypes
NumControllerTypes
} ;
controller( ControllerTypes _type, model * _parent );

View File

@@ -1,5 +1,5 @@
/*
* controller_connection.h - declaration of a controller connect, which
* controller_connection.h - declaration of a controller connect, which
* provides a definition of the link between a controller and
* model, also handles deferred creation of links while
* loading project
@@ -37,7 +37,7 @@
#include "mv_base.h"
#include "journalling_object.h"
class controllerConnection;
class controllerConnection;
typedef QVector<controllerConnection *> controllerConnectionVector;
@@ -51,26 +51,26 @@ public:
virtual ~controllerConnection();
inline controller * getController( void )
{
return m_controller;
}
inline controller * getController( void )
{
return m_controller;
}
inline void setController( controller * _controller );
inline void setController( controller * _controller );
inline void setController( int _controllerId );
inline void setController( int _controllerId );
float currentValue( int _offset )
{
return m_controller->currentValue( _offset );
}
float currentValue( int _offset )
{
return m_controller->currentValue( _offset );
}
inline bool isFinalized( void )
{
return m_controllerId < 0;
}
inline bool isFinalized( void )
{
return m_controllerId < 0;
}
static void finalizeConnections( void );
static void finalizeConnections( void );
virtual void saveSettings( QDomDocument & _doc, QDomElement & _this );
virtual void loadSettings( const QDomElement & _this );
@@ -80,9 +80,10 @@ protected:
//virtual controllerDialog * createDialog( QWidget * _parent );
controller * m_controller;
int m_controllerId;
int m_controllerId;
bool m_ownsController;
static controllerConnectionVector s_connections;
static controllerConnectionVector s_connections;
signals:
// The value changed while the mixer isn't running (i.e: MIDI CC)

View File

@@ -40,7 +40,9 @@ class QListView;
class QScrollArea;
class groupBox;
class lcdSpinBox;
class ledCheckBox;
class comboBox;
class autoDetectMidiController;
@@ -59,13 +61,19 @@ public:
public slots:
// void setSelection( const effectKey & _selection );
void selectController( void );
void midiToggled( void );
void userToggled( void );
void autoDetectToggled( void );
void midiValueChanged( void );
private:
// effectKey m_currentSelection;
//
groupBox * m_midiGroupBox;
lcdSpinBox * m_midiChannel;
lcdSpinBox * m_midiController;
lcdSpinBox * m_midiChannelSpinBox;
lcdSpinBox * m_midiControllerSpinBox;
ledCheckBox * m_midiAutoDetectCheckBox;
boolModel m_midiAutoDetect;
groupBox * m_userGroupBox;
comboBox * m_userController;
@@ -74,53 +82,8 @@ private:
controller * m_controller;
// Temporary midiController
autoDetectMidiController * m_midiController;
} ;
/*
class effectListWidget : public QWidget
{
Q_OBJECT
public:
effectListWidget( QWidget * _parent );
virtual ~effectListWidget();
inline effectKey getSelected( void )
{
return( m_currentSelection );
}
signals:
void highlighted( const effectKey & _key );
void addPlugin( const effectKey & _key );
void doubleClicked( const effectKey & _key );
protected:
virtual void resizeEvent( QResizeEvent * );
protected slots:
void rowChanged( const QModelIndex &, const QModelIndex & );
void onAddButtonReleased( void );
void onDoubleClicked( const QModelIndex & );
private:
QVector<plugin::descriptor> m_pluginDescriptors;
effectKeyList m_effectKeys;
effectKey m_currentSelection;
QLineEdit * m_filterEdit;
QListView * m_pluginList;
QStandardItemModel m_sourceModel;
QSortFilterProxyModel m_model;
QScrollArea * m_scrollArea;
QWidget * m_descriptionWidget;
} ;
*/
#endif

View File

@@ -79,7 +79,8 @@ enum midiMetaEvents
} ;
const Sint8 MIDI_CHANNEL_COUNT = 16;
const Uint8 MIDI_CHANNEL_COUNT = 16;
const Uint8 MIDI_CONTROLLER_COUNT = 128;
struct midiEvent
@@ -129,6 +130,7 @@ struct midiEvent
union
{
Uint16 m_param[2]; // first/second parameter (key/velocity)
Uint8 m_bytes[4]; // raw bytes
Uint32 m_sysExDataLen; // len of m_sysExData
} m_data;

97
include/midi_controller.h Normal file
View File

@@ -0,0 +1,97 @@
/*
* midi_controller.h - A controller to receive MIDI control-changes
*
* Copyright (c) 2008 Paul Giblock <drfaygo/at/gmail.com>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program (see COPYING); if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
*/
#ifndef _MIDI_CONTROLLER_H
#define _MIDI_CONTROLLER_H
#include <QtGui/QWidget>
#include "mv_base.h"
#include "automatable_model.h"
#include "controller.h"
#include "controller_dialog.h"
#include "midi_event_processor.h"
class midiPort;
class midiController : public controller, public midiEventProcessor
{
Q_OBJECT
public:
midiController( model * _parent );
virtual ~midiController();
virtual QString publicName() const
{
return "MIDI Controller";
}
virtual void processInEvent( const midiEvent & _me,
const midiTime & _time,
bool _lock = TRUE );
virtual void processOutEvent( const midiEvent& _me,
const midiTime & _time)
{
// No output yet
}
virtual void saveSettings( QDomDocument & _doc, QDomElement & _this );
virtual void loadSettings( const QDomElement & _this );
virtual QString nodeName( void ) const;
virtual intModel * midiChannelModel( void )
{
return &m_midiChannel;
}
virtual intModel * midiControllerModel( void )
{
return &m_midiController;
}
public slots:
virtual controllerDialog * createDialog( QWidget * _parent );
void updateMidiPort();
protected:
// The internal per-controller get-value function
virtual float value( int _offset );
intModel m_midiChannel;
intModel m_midiController;
midiPort * m_midiPort;
float m_lastValue;
};
#endif

View File

@@ -77,6 +77,11 @@ automatableModel::~automatableModel()
m_linkedModels.last()->unlinkModel( this );
m_linkedModels.erase( m_linkedModels.end() - 1 );
}
if( m_controllerConnection )
{
delete m_controllerConnection;
}
}

View File

@@ -48,7 +48,7 @@ controller::controller( ControllerTypes _type, model * _parent ) :
journallingObject(),
m_type( _type )
{
if( _type != DummyController )
if( _type != DummyController && _type != MidiController )
{
s_controllers.append( this );
m_name = QString( tr( "Controller %1" ) )
@@ -60,7 +60,11 @@ controller::controller( ControllerTypes _type, model * _parent ) :
controller::~controller()
{
s_controllers.remove( s_controllers.indexOf( this ) );
int idx = s_controllers.indexOf( this );
if( idx >= 0 )
{
s_controllers.remove( idx );
}
if( engine::getSong() )
{

View File

@@ -41,7 +41,8 @@ controllerConnectionVector controllerConnection::s_connections;
controllerConnection::controllerConnection( controller * _controller ) :
m_controllerId( -1 )
m_controllerId( -1 ),
m_ownsController( FALSE )
{
if( _controller != NULL )
{
@@ -58,7 +59,8 @@ controllerConnection::controllerConnection( controller * _controller ) :
controllerConnection::controllerConnection( int _controllerId ) :
m_controller( controller::create( controller::DummyController, NULL ) ),
m_controllerId( _controllerId )
m_controllerId( _controllerId ),
m_ownsController( FALSE )
{
s_connections.append( this );
}
@@ -68,6 +70,10 @@ controllerConnection::controllerConnection( int _controllerId ) :
controllerConnection::~controllerConnection()
{
s_connections.remove( s_connections.indexOf( this ) );
if( m_ownsController )
{
delete m_controller;
}
}
@@ -80,13 +86,22 @@ void controllerConnection::setController( int _controllerId )
void controllerConnection::setController( controller * _controller )
{
if( m_ownsController && m_controller )
{
delete m_controller;
}
m_controller = _controller;
m_controllerId = -1;
if( _controller->type() != controller::DummyController ) {
if( _controller->type() != controller::DummyController )
{
QObject::connect( _controller, SIGNAL( valueChanged() ),
this, SIGNAL( valueChanged() ) );
}
m_ownsController =
( _controller->type() == controller::MidiController );
}

View File

@@ -245,13 +245,17 @@ void midiClientRaw::parseData( const Uint8 _c )
case NOTE_OFF:
case NOTE_ON:
case KEY_PRESSURE:
case CONTROL_CHANGE:
case PROGRAM_CHANGE:
case CHANNEL_PRESSURE:
m_midiParseData.m_midiEvent.m_data.m_param[0] =
m_midiParseData.m_buffer[0] - KeysPerOctave;
m_midiParseData.m_midiEvent.m_data.m_param[1] =
m_midiParseData.m_buffer[1];
case CONTROL_CHANGE:
m_midiParseData.m_midiEvent.m_data.m_param[0] =
m_midiParseData.m_buffer[0] - KeysPerOctave;
m_midiParseData.m_midiEvent.m_data.m_param[1] =
m_midiParseData.m_buffer[1];
break;
case PITCH_BEND:

View File

@@ -0,0 +1,159 @@
#ifndef SINGLE_SOURCE_COMPILE
/*
* midi_controller.cpp - implementation of class midi-controller which handles
* MIDI control change messages
*
* Copyright (c) 2008 Paul Giblock <drfaygo/at/gmail.com>
*
* 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 <Qt/QtXml>
#include <QtCore/QObject>
#include <QtCore/QVector>
#include "song.h"
#include "engine.h"
#include "mixer.h"
#include "midi_client.h"
#include "midi_port.h"
#include "midi_controller.h"
midiController::midiController( model * _parent ) :
controller( MidiController, _parent ),
midiEventProcessor(),
m_midiChannel( 0, 0, MIDI_CHANNEL_COUNT, this ),
m_midiController( 0, 0, MIDI_CONTROLLER_COUNT, this ),
m_midiPort( engine::getMixer()->getMIDIClient()->addPort(
this, tr( "unnamed_channel" ) ) ),
m_lastValue( 0.0f )
{
m_midiPort->setMode( midiPort::Input );
connect( &m_midiChannel, SIGNAL( dataChanged() ),
this, SLOT( updateMidiPort() ) );
connect( &m_midiController, SIGNAL( dataChanged() ),
this, SLOT( updateMidiPort() ) );
}
midiController::~midiController()
{
m_midiChannel.disconnect( this );
m_midiController.disconnect( this );
engine::getMixer()->getMIDIClient()->removePort( m_midiPort );
}
float midiController::value( int _offset )
{
return m_lastValue;
}
void midiController::updateMidiPort( void )
{
m_midiPort->setInputChannel( m_midiChannel.value() - 1 );
}
void midiController::processInEvent( const midiEvent & _me,
const midiTime & _time, bool _lock )
{
Uint8 controllerNum;
const Uint8 * bytes;
switch( _me.m_type )
{
case CONTROL_CHANGE:
bytes = _me.m_data.m_bytes;
controllerNum = _me.m_data.m_bytes[0] & 0x7F;
if( m_midiController.value() == controllerNum + 1 &&
( m_midiChannel.value() == _me.m_channel + 1 ||
m_midiChannel.value() == 0 ) )
{
Uint8 val = _me.m_data.m_bytes[2] & 0x7F;
m_lastValue = (float)( val ) / 127.0f;
emit valueChanged();
}
break;
default:
// Don't care - maybe add special cases for pitch and mod later
break;
}
}
void midiController::saveSettings( QDomDocument & _doc, QDomElement & _this )
{
controller::saveSettings( _doc, _this );
m_midiChannel.saveSettings( _doc, _this, "channel" );
m_midiController.saveSettings( _doc, _this, "controller" );
}
void midiController::loadSettings( const QDomElement & _this )
{
controller::loadSettings( _this );
m_midiChannel.loadSettings( _this, "channel" );
m_midiController.loadSettings( _this, "controller" );
updateMidiPort();
}
QString midiController::nodeName( void ) const
{
return( "midicontroller" );
}
controllerDialog * midiController::createDialog( QWidget * _parent )
{
return NULL;
}
#include "midi_controller.moc"
#endif

View File

@@ -409,8 +409,8 @@ void trackContentObjectView::mousePressEvent( QMouseEvent * _me )
s_textFloat->setTitle( tr( "Current position" ) );
delete m_hint;
m_hint = textFloat::displayMessage( tr( "Hint" ),
tr( "Press <Ctrl> for free "
"positioning." ),
tr( "Press <Ctrl> and drag to make "
"a copy." ),
embed::getIconPixmap( "hint" ), 0 );
}
else if( m_autoResize == FALSE )

View File

@@ -33,18 +33,88 @@
#include "controller_connection_dialog.h"
#include "lcd_spinbox.h"
#include "led_checkbox.h"
#include "combobox.h"
#include "group_box.h"
#include "midi_controller.h"
#include "midi.h"
#include "song.h"
#include "gui_templates.h"
#include "embed.h"
class autoDetectMidiController : public midiController
{
public:
autoDetectMidiController( model * _parent ) :
midiController( _parent ),
m_detectedMidiChannel( 0 ),
m_detectedMidiController( 0 )
{
updateMidiPort();
}
virtual ~autoDetectMidiController()
{
}
virtual void processInEvent( const midiEvent & _me,
const midiTime & _time, bool _lock )
{
if( _me.m_type == CONTROL_CHANGE &&
( m_midiChannel.value() == _me.m_channel + 1 ||
m_midiChannel.value() == 0 ) )
{
m_detectedMidiChannel = _me.m_channel + 1;
m_detectedMidiController = ( _me.m_data.m_bytes[0] & 0x7F ) + 1;
emit valueChanged();
}
}
int m_detectedMidiChannel;
int m_detectedMidiController;
// Would be a nice copy ctor, but too hard to add copy ctor because
// model has none.
midiController * copyToMidiController( model * _parent )
{
midiController * c = new midiController( _parent );
c->midiChannelModel()->setValue( m_midiChannel.value() );
c->midiControllerModel()->setValue( m_midiController.value() );
return c;
}
void useDetected( void )
{
m_midiChannel.setValue( m_detectedMidiChannel );
m_midiController.setValue( m_detectedMidiController );
}
public slots:
void reset( void )
{
m_midiChannel.setValue( 0 );
m_midiController.setValue( 0 );
}
};
controllerConnectionDialog::controllerConnectionDialog( QWidget * _parent
) :
QDialog( _parent ),
m_controller( NULL )
m_controller( NULL ),
m_midiController( NULL ),
m_midiAutoDetect( FALSE )
{
setWindowIcon( embed::getIconPixmap( "setup_audio" ) );
setWindowTitle( tr( "Connection Settings" ) );
@@ -54,11 +124,39 @@ controllerConnectionDialog::controllerConnectionDialog( QWidget * _parent
vlayout->setSpacing( 10 );
vlayout->setMargin( 10 );
// Midi stuff
m_midiGroupBox = new groupBox( tr( "MIDI CONTROLLER" ), this );
m_midiGroupBox->setGeometry( 2, 2, 240, 64 );
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, 16 );
m_midiControllerSpinBox = new lcdSpinBox( 3, m_midiGroupBox,
tr( "Input controller" ) );
m_midiControllerSpinBox->addTextForValue( 0, "---" );
m_midiControllerSpinBox->setLabel( tr( "CONTROLLER" ) );
m_midiControllerSpinBox->move( 72, 16 );
ledCheckBox * m_midiAutoDetectCheckBox =
new ledCheckBox( tr("Auto Detect"),
m_midiGroupBox, tr("Auto Detect") );
m_midiAutoDetectCheckBox->setModel( &m_midiAutoDetect );
m_midiAutoDetectCheckBox->move( 136, 20 );
connect( &m_midiAutoDetect, SIGNAL( dataChanged() ),
this, SLOT( autoDetectToggled() ) );
// User stuff
m_userGroupBox = new groupBox( tr( "USER CONTROLLER" ), this );
m_userGroupBox->setGeometry( 2, 70, 240, 64 );
connect( m_userGroupBox->model(), SIGNAL( dataChanged() ),
this, SLOT( userToggled() ) );
m_mappingFunction = new QLineEdit( this );
m_mappingFunction->setGeometry( 2, 140, 240, 16 );
@@ -66,7 +164,7 @@ controllerConnectionDialog::controllerConnectionDialog( QWidget * _parent
QWidget * buttons = new QWidget( this );
buttons->setGeometry( 2, 160, 240, 32 );
resize( 256, 196 );
m_userController = new comboBox( m_userGroupBox, "Controller" );
@@ -113,201 +211,106 @@ controllerConnectionDialog::controllerConnectionDialog( QWidget * _parent
controllerConnectionDialog::~controllerConnectionDialog()
{
if( m_midiController )
delete m_midiController;
}
/*
void effectSelectDialog::setSelection( const effectKey & _selection )
{
m_currentSelection = _selection;
}
*/
void controllerConnectionDialog::selectController( void )
{
if( m_userController->model()->value() >= 0 ) {
m_controller = engine::getSong()->controllers().at(
m_userController->model()->value() );
if( m_midiGroupBox->model()->value() >= 0 )
{
m_controller = m_midiController->copyToMidiController(
engine::getSong() );
}
else
{
if( m_userController->model()->value() >= 0 )
{
m_controller = engine::getSong()->controllers().at(
m_userController->model()->value() );
}
}
accept();
}
/*
effectListWidget::effectListWidget( QWidget * _parent ) :
QWidget( _parent ),
m_sourceModel(),
m_model(),
m_descriptionWidget( NULL )
void controllerConnectionDialog::midiToggled( void )
{
plugin::getDescriptorsOfAvailPlugins( m_pluginDescriptors );
for( QVector<plugin::descriptor>::iterator it =
m_pluginDescriptors.begin();
it != m_pluginDescriptors.end(); ++it )
int enabled = m_midiGroupBox->model()->value();
if( enabled != 0 )
{
if( it->type != plugin::Effect )
if( m_userGroupBox->model()->value() != 0 )
{
continue;
m_userGroupBox->model()->setValue( 0 );
}
if( it->sub_plugin_features )
{
it->sub_plugin_features->listSubPluginKeys(
// as iterators are always stated to be not
// equal with pointers, we dereference the
// iterator and take the address of the item,
// so we're on the safe side and the compiler
// likely will reduce that to just "it"
&( *it ),
m_effectKeys );
}
else
{
m_effectKeys << effectKey( &( *it ), it->name );
if( !m_midiController )
{
m_midiController = new autoDetectMidiController( engine::getSong() );
m_midiChannelSpinBox->setModel(
m_midiController->midiChannelModel() );
m_midiControllerSpinBox->setModel(
m_midiController->midiControllerModel() );
connect( m_midiController, SIGNAL( valueChanged() ),
this, SLOT( midiValueChanged() ) );
}
}
QStringList plugin_names;
for( effectKeyList::const_iterator it = m_effectKeys.begin();
it != m_effectKeys.end(); ++it )
else
{
plugin_names += QString( ( *it ).desc->public_name ) +
( ( ( *it ).desc->sub_plugin_features != NULL ) ?
": " + ( *it ).name
:
"" );
m_midiAutoDetect.setValue( FALSE );
}
m_midiChannelSpinBox->setEnabled( enabled );
m_midiControllerSpinBox->setEnabled( enabled );
//m_midiAutoDetect->setEnabled( enabled );
}
int row = 0;
for( QStringList::iterator it = plugin_names.begin();
it != plugin_names.end(); ++it )
void controllerConnectionDialog::userToggled( void )
{
int enabled = m_userGroupBox->model()->value();
if( enabled != 0 && m_midiGroupBox->model()->value() != 0 )
{
m_sourceModel.setItem( row, 0, new QStandardItem( *it ) );
++row;
m_midiGroupBox->model()->setValue( 0 );
}
m_model.setSourceModel( &m_sourceModel );
m_model.setFilterCaseSensitivity( Qt::CaseInsensitive );
m_userController->setEnabled( enabled );
}
m_filterEdit = new QLineEdit( this );
connect( m_filterEdit, SIGNAL( textChanged( const QString & ) ),
&m_model, SLOT( setFilterRegExp( const QString & ) ) );
m_pluginList = new QListView( this );
m_pluginList->setModel( &m_model );
QItemSelectionModel * sm = new QItemSelectionModel( &m_model );
m_pluginList->setSelectionModel( sm );
m_pluginList->setSelectionBehavior( QAbstractItemView::SelectRows );
m_pluginList->setSelectionMode( QAbstractItemView::SingleSelection );
m_pluginList->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
connect( sm, SIGNAL( currentRowChanged( const QModelIndex &,
const QModelIndex & ) ),
SLOT( rowChanged( const QModelIndex &,
const QModelIndex & ) ) );
connect( m_pluginList, SIGNAL( doubleClicked( const QModelIndex & ) ),
SLOT( onDoubleClicked( const QModelIndex & ) ) );
QGroupBox * groupbox = new QGroupBox( tr( "Description" ), this );
groupbox->setFixedHeight( 200 );
QVBoxLayout * gbl = new QVBoxLayout( groupbox );
gbl->setMargin( 0 );
gbl->setSpacing( 10 );
m_scrollArea = new QScrollArea( groupbox );
m_scrollArea->setFrameStyle( 0 );
gbl->addWidget( m_scrollArea );
QVBoxLayout * vboxl = new QVBoxLayout( this );
vboxl->setMargin( 0 );
vboxl->setSpacing( 10 );
vboxl->addWidget( m_filterEdit );
vboxl->addWidget( m_pluginList );
vboxl->addWidget( groupbox );
if( m_sourceModel.rowCount() > 0 )
void controllerConnectionDialog::autoDetectToggled( void )
{
if( m_midiAutoDetect.value() )
{
// m_pluginList->setCurrentRow( 0 );
//rowChanged( 0 );
m_midiController->reset();
}
}
effectListWidget::~effectListWidget()
void controllerConnectionDialog::midiValueChanged( void )
{
}
void effectListWidget::rowChanged( const QModelIndex & _idx,
const QModelIndex & )
{
delete m_descriptionWidget;
m_descriptionWidget = NULL;
m_currentSelection = m_effectKeys[_idx.row()];
if( m_currentSelection.desc &&
m_currentSelection.desc->sub_plugin_features )
if( m_midiAutoDetect.value() )
{
m_descriptionWidget = new QWidget;
QVBoxLayout * l = new QVBoxLayout( m_descriptionWidget );
l->setMargin( 4 );
l->setSpacing( 0 );
m_midiController->useDetected();
m_scrollArea->setWidget( m_descriptionWidget );
m_currentSelection.desc->sub_plugin_features->
fillDescriptionWidget( m_descriptionWidget,
&m_currentSelection );
foreach( QWidget * w,
m_descriptionWidget->findChildren<QWidget *>() )
{
if( w->parent() == m_descriptionWidget )
{
l->addWidget( w );
}
}
l->setSizeConstraint( QLayout::SetFixedSize );
m_descriptionWidget->show();
m_midiAutoDetect.setValue( FALSE );
}
emit( highlighted( m_currentSelection ) );
}
void effectListWidget::onDoubleClicked( const QModelIndex & )
{
emit( doubleClicked( m_currentSelection ) );
}
void effectListWidget::onAddButtonReleased()
{
emit( addPlugin( m_currentSelection ) );
}
void effectListWidget::resizeEvent( QResizeEvent * )
{
//m_descriptionWidget->setFixedWidth( width() - 40 );
}
*/
#include "controller_connection_dialog.moc"
#endif

View File

@@ -291,6 +291,10 @@ void instrumentTrack::processInEvent( const midiEvent & _me,
m_instrument->handleMidiEvent( _me, _time );
break;
case CONTROL_CHANGE:
// Ignore control changes
break;
default:
printf( "instrument-track: unhandled MIDI-event %d\n",
_me.m_type );

View File

@@ -1151,7 +1151,7 @@ void patternView::paintEvent( QPaintEvent * )
p.drawLine(
x_base + static_cast<int>(
ppt * tact_num ) - 1,
height() - ( 5 + 2 *
height() - ( 4 + 2 *
TCO_BORDER_WIDTH ),
x_base + static_cast<int>(
ppt * tact_num ) - 1,