LVSL: added support for (automatable) VST controls and VST presets

LMMS VST Support Layer has been greatly advanced as it now features
(automatable) VST controls as well as support for VST presets. This
still needs some work as it crashes with various plugins (e.g. z3ta+).

Signed-off-by: Tobias Doerffel <tobias.doerffel@gmail.com>
This commit is contained in:
quadro
2011-10-22 20:14:28 +02:00
committed by Tobias Doerffel
parent c6051e76b4
commit 4d645b335d
21 changed files with 1620 additions and 31 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 510 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 516 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 514 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 548 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 519 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 491 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 516 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 528 B

View File

@@ -509,6 +509,11 @@ enum RemoteMessageIDs
IdSaveSettingsToFile,
IdLoadSettingsFromString,
IdLoadSettingsFromFile,
IdLoadChunkFromPresetFile,
IdRotateProgram,
IdLoadPrograms,
IdSavePreset,
IdSetParameter,
IdLoadPresetFromFile,
IdDebugMessage,
IdUserBase = 64

View File

@@ -180,7 +180,7 @@ public:
class VstParameterProperties
{
public:
float stepFloat;
/* float stepFloat;
char label[64];
int flags;
int minInteger;
@@ -189,7 +189,24 @@ public:
char shortLabel[8];
int category;
char categoryLabel[24];
char empty[128];
char empty[128];*/
float stepFloat;
float smallStepFloat;
float largeStepFloat;
char label[64];
unsigned int flags;
unsigned int minInteger;
unsigned int maxInteger;
unsigned int stepInteger;
unsigned int largeStepInteger;
char shortLabel[8];
unsigned short displayIndex;
unsigned short category;
unsigned short numParametersInCategory;
unsigned short reserved;
char categoryLabel[24];
char future[16];
} ;

View File

@@ -1,7 +1,7 @@
/*
* vestige.cpp - instrument-plugin for hosting VST-instruments
*
* Copyright (c) 2005-2009 Tobias Doerffel <tobydox/at/users.sourceforge.net>
* Copyright (c) 2005-2011 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*
@@ -29,6 +29,8 @@
#include <QtGui/QMessageBox>
#include <QtGui/QPainter>
#include <QtGui/QPushButton>
#include <QtGui/QMdiArea>
#include <QtGui/QMenu>
#include <QtXml/QDomElement>
#include "engine.h"
@@ -36,6 +38,7 @@
#include "InstrumentPlayHandle.h"
#include "InstrumentTrack.h"
#include "VstPlugin.h"
#include "MainWindow.h"
#include "pixmap_button.h"
#include "string_pair_drag.h"
#include "text_float.h"
@@ -44,6 +47,7 @@
#include "embed.cpp"
extern "C"
{
@@ -65,12 +69,16 @@ Plugin::Descriptor PLUGIN_EXPORT vestige_plugin_descriptor =
QPixmap * VestigeInstrumentView::s_artwork = NULL;
QPixmap * manageVestigeInstrumentView::s_artwork = NULL;
vestigeInstrument::vestigeInstrument( InstrumentTrack * _instrument_track ) :
Instrument( _instrument_track, &vestige_plugin_descriptor ),
m_plugin( NULL ),
m_pluginMutex()
m_pluginMutex(),
m_subWindow( NULL ),
knobFModel( NULL ),
vstKnobs( NULL )
{
// now we need a play-handle which cares for calling play()
InstrumentPlayHandle * iph = new InstrumentPlayHandle( this );
@@ -96,6 +104,28 @@ void vestigeInstrument::loadSettings( const QDomElement & _this )
if( m_plugin != NULL )
{
m_plugin->loadSettings( _this );
const QMap<QString, QString> & dump = m_plugin->parameterDump();
int paramCount = (dump).size();
char paramStr[35];
vstKnobs = new knob *[paramCount];
knobFModel = new FloatModel *[paramCount];
QStringList list1;
QWidget * xx = new QWidget();
for (int i = 0; i < paramCount; i++) {
sprintf( paramStr, "param%d", i);
list1 = dump[paramStr].split(":");
vstKnobs[i] = new knob( knobBright_26, xx );
vstKnobs[i]->setHintText( list1.at(1) + ":", "");
vstKnobs[i]->setLabel( list1.at(1).left(15) );
knobFModel[i] = new FloatModel( (list1.at(2)).toFloat(), 0.0f, 1.0f, 0.01f, this, QString::number(i) );
knobFModel[i]->loadSettings( _this, paramStr );
connect( knobFModel[i], SIGNAL( dataChanged() ), this, SLOT( setParameter() ) );
vstKnobs[i]->setModel( knobFModel[i] );
}
}
m_pluginMutex.unlock();
}
@@ -103,6 +133,20 @@ void vestigeInstrument::loadSettings( const QDomElement & _this )
void vestigeInstrument::setParameter( void )
{
Model *action = qobject_cast<Model *>(sender());
int knobUNID = action->displayName().toInt();
if ( m_plugin != NULL ) {
m_plugin->setParam( knobUNID, knobFModel[knobUNID]->value() );
}
}
void vestigeInstrument::saveSettings( QDomDocument & _doc, QDomElement & _this )
{
_this.setAttribute( "plugin", m_pluginDLL );
@@ -110,6 +154,40 @@ void vestigeInstrument::saveSettings( QDomDocument & _doc, QDomElement & _this )
if( m_plugin != NULL )
{
m_plugin->saveSettings( _doc, _this );
if (knobFModel != NULL) {
const QMap<QString, QString> & dump = m_plugin->parameterDump();
int paramCount = (dump).size();
char paramStr[35];
for (int i = 0; i < paramCount; i++) {
if (knobFModel[i]->isAutomated() || knobFModel[i]->getControllerConnection()) {
sprintf( paramStr, "param%d", i);
knobFModel[i]->saveSettings( _doc, _this, paramStr );
}
/* QDomElement me = _doc.createElement( paramStr );
me.setAttribute( "id", knobFModel[i]->id() );
me.setAttribute( "value", knobFModel[i]->value() );
_this.appendChild( me );
ControllerConnection * m_controllerConnection = knobFModel[i]->getControllerConnection();
if (m_controllerConnection) {
QDomElement controller_element;
QDomNode node = _this.namedItem( "connection" );
if( node.isElement() )
{
controller_element = node.toElement();
}
else
{
controller_element = _doc.createElement( "connection" );
_this.appendChild( controller_element );
}
QDomElement element = _doc.createElement( paramStr );
m_controllerConnection->saveSettings( _doc, element );
controller_element.appendChild( element );
}*/
}
}
}
m_pluginMutex.unlock();
}
@@ -246,7 +324,9 @@ PluginView * vestigeInstrument::instantiateView( QWidget * _parent )
VestigeInstrumentView::VestigeInstrumentView( Instrument * _instrument,
QWidget * _parent ) :
InstrumentView( _instrument, _parent )
InstrumentView( _instrument, _parent ),
tt ( NULL ),
lastPosInMenu (0)
{
if( s_artwork == NULL )
{
@@ -271,8 +351,108 @@ VestigeInstrumentView::VestigeInstrumentView( Instrument * _instrument,
"clicking on this button, a file-open-dialog appears "
"and you can select your file." ) );
m_managePluginButton = new pixmapButton( this, "" );
m_managePluginButton->setCheckable( false );
m_managePluginButton->setCursor( Qt::PointingHandCursor );
m_managePluginButton->move( 220, 102 );
m_managePluginButton->setActiveGraphic( PLUGIN_NAME::getIconPixmap(
"track_op_menu", 20, 20 ) );
m_managePluginButton->setInactiveGraphic( PLUGIN_NAME::getIconPixmap(
"track_op_menu", 20, 20 ) );
connect( m_managePluginButton, SIGNAL( clicked() ), this,
SLOT( managePlugin() ) );
toolTip::add( m_managePluginButton, tr( "Control VST-plugin from LMMS host" ) );
m_managePluginButton->setWhatsThis(
tr( "Click here, if you want to control VST-plugin from host." ) );
m_openPresetButton = new pixmapButton( this, "" );
m_openPresetButton->setCheckable( false );
m_openPresetButton->setCursor( Qt::PointingHandCursor );
m_openPresetButton->move( 224, 192 );
m_openPresetButton->setActiveGraphic( PLUGIN_NAME::getIconPixmap(
"stepper-up-press" ) );
m_openPresetButton->setInactiveGraphic( PLUGIN_NAME::getIconPixmap(
"stepper-up" ) );
connect( m_openPresetButton, SIGNAL( clicked() ), this,
SLOT( openPreset() ) );
toolTip::add( m_openPresetButton, tr( "Open VST-plugin preset" ) );
m_openPresetButton->setWhatsThis(
tr( "Click here, if you want to open another *.fxp, *.fxb VST-plugin preset." ) );
m_rolLPresetButton = new pixmapButton( this, "" );
m_rolLPresetButton->setCheckable( false );
m_rolLPresetButton->setCursor( Qt::PointingHandCursor );
m_rolLPresetButton->move( 167, 192 );
m_rolLPresetButton->setActiveGraphic( PLUGIN_NAME::getIconPixmap(
"stepper-left-press" ) );
m_rolLPresetButton->setInactiveGraphic( PLUGIN_NAME::getIconPixmap(
"stepper-left" ) );
connect( m_rolLPresetButton, SIGNAL( clicked() ), this,
SLOT( rolrPreset() ) );
toolTip::add( m_rolLPresetButton, tr( "Previous (-)" ) );
m_rolLPresetButton->setShortcut( Qt::Key_Minus );
m_rolLPresetButton->setWhatsThis(
tr( "Click here, if you want to switch to another VST-plugin presset program." ) );
m_savePresetButton = new pixmapButton( this, "" );
m_savePresetButton->setCheckable( false );
m_savePresetButton->setCursor( Qt::PointingHandCursor );
m_savePresetButton->move( 224, 213 );
m_savePresetButton->setActiveGraphic( PLUGIN_NAME::getIconPixmap(
"project_save", 16, 16 ) );
m_savePresetButton->setInactiveGraphic( PLUGIN_NAME::getIconPixmap(
"project_save", 16, 16 ) );
connect( m_savePresetButton, SIGNAL( clicked() ), this,
SLOT( savePreset() ) );
toolTip::add( m_savePresetButton, tr( "Save preset" ) );
m_savePresetButton->setWhatsThis(
tr( "Click here, if you want to save current VST-plugin presset program." ) );
m_rolRPresetButton = new pixmapButton( this, "" );
m_rolRPresetButton->setCheckable( false );
m_rolRPresetButton->setCursor( Qt::PointingHandCursor );
m_rolRPresetButton->move( 186, 192 );
m_rolRPresetButton->setActiveGraphic( PLUGIN_NAME::getIconPixmap(
"stepper-right-press" ) );
m_rolRPresetButton->setInactiveGraphic( PLUGIN_NAME::getIconPixmap(
"stepper-right" ) );
connect( m_rolRPresetButton, SIGNAL( clicked() ), this,
SLOT( rollPreset() ) );
toolTip::add( m_rolRPresetButton, tr( "Next (+)" ) );
m_rolRPresetButton->setShortcut( Qt::Key_Plus );
m_rolRPresetButton->setWhatsThis(
tr( "Click here, if you want to switch to another VST-plugin presset program." ) );
m_selPresetButton = new QPushButton( tr( "" ), this );
m_selPresetButton->setGeometry( 205, 192, 16, 16 );
QMenu *menu = new QMenu;
connect( menu, SIGNAL( aboutToShow() ), this, SLOT( updateMenu() ) );
m_selPresetButton->setIcon( PLUGIN_NAME::getIconPixmap( "stepper-down" ) );
m_selPresetButton->setWhatsThis(
tr( "Click here to select presets that are currently loaded in VST." ) );
m_selPresetButton->setMenu(menu);
m_toggleGUIButton = new QPushButton( tr( "Show/hide GUI" ), this );
m_toggleGUIButton->setGeometry( 20, 150, 200, 24 );
m_toggleGUIButton->setGeometry( 20, 130, 200, 24 );
m_toggleGUIButton->setIcon( embed::getIconPixmap( "zoom" ) );
m_toggleGUIButton->setFont( pointSize<8>( m_toggleGUIButton->font() ) );
connect( m_toggleGUIButton, SIGNAL( clicked() ), this,
@@ -283,16 +463,60 @@ VestigeInstrumentView::VestigeInstrumentView( Instrument * _instrument,
QPushButton * note_off_all_btn = new QPushButton( tr( "Turn off all "
"notes" ), this );
note_off_all_btn->setGeometry( 20, 180, 200, 24 );
note_off_all_btn->setGeometry( 20, 160, 200, 24 );
note_off_all_btn->setIcon( embed::getIconPixmap( "state_stop" ) );
note_off_all_btn->setFont( pointSize<8>( note_off_all_btn->font() ) );
connect( note_off_all_btn, SIGNAL( clicked() ), this,
SLOT( noteOffAll() ) );
setAcceptDrops( true );
_instrument2 = _instrument;
_parent2 = _parent;
}
void VestigeInstrumentView::managePlugin( void )
{
if ( m_vi->m_plugin != NULL && m_vi->m_subWindow == NULL ) {
tt = new manageVestigeInstrumentView( _instrument2, _parent2, m_vi);
} else if (m_vi->m_subWindow != NULL) {
m_vi->m_scrollArea->show();
m_vi->m_subWindow->show();
}
}
void VestigeInstrumentView::updateMenu( void )
{
// get all presets -
if ( m_vi->m_plugin != NULL ) {
m_vi->m_plugin->loadPrograms( 1 );
QWidget::update();
QString str = m_vi->m_plugin->presetsString();
QStringList list1 = str.split("|");
QMenu * to_menu = m_selPresetButton->menu();
to_menu->clear();
QAction *presetActions[list1.size()];
for (int i = 0; i < list1.size(); i++) {
presetActions[i] = new QAction(this);
connect(presetActions[i], SIGNAL(triggered()), this, SLOT(selPreset()));
presetActions[i]->setText(QString("%1. %2").arg(QString::number(i+1), list1.at(i)));
presetActions[i]->setData(i);
if (i == lastPosInMenu) {
presetActions[i]->setIcon(embed::getIconPixmap( "sample_file", 16, 16 ));
} else presetActions[i]->setIcon(embed::getIconPixmap( "edit_copy", 16, 16 ));
to_menu->addAction( presetActions[i] );
}
}
}
VestigeInstrumentView::~VestigeInstrumentView()
@@ -346,6 +570,12 @@ void VestigeInstrumentView::openPlugin( void )
return;
}
engine::getMixer()->lock();
if (tt != NULL) {
delete tt;
tt = NULL;
}
m_vi->loadFile( ofd.selectedFiles()[0] );
engine::getMixer()->unlock();
if( m_vi->m_plugin && m_vi->m_plugin->pluginWidget() )
@@ -359,6 +589,87 @@ void VestigeInstrumentView::openPlugin( void )
void VestigeInstrumentView::openPreset( void )
{
if ( m_vi->m_plugin != NULL ) {
m_vi->m_plugin->openPreset( );
bool converted;
QString str = m_vi->m_plugin->presetString().section("/", 0, 0);
if (str != "")
lastPosInMenu = str.toInt(&converted, 10) - 1;
QWidget::update();
}
}
void VestigeInstrumentView::savePreset( void )
{
if ( m_vi->m_plugin != NULL ) {
m_vi->m_plugin->savePreset( );
/* bool converted;
QString str = m_vi->m_plugin->presetString().section("/", 0, 0);
if (str != "")
lastPosInMenu = str.toInt(&converted, 10) - 1;
QWidget::update();*/
}
}
void VestigeInstrumentView::rollPreset( void )
{
if ( m_vi->m_plugin != NULL ) {
m_vi->m_plugin->rollPreset( 1 );
bool converted;
QString str = m_vi->m_plugin->presetString().section("/", 0, 0);
if (str != "")
lastPosInMenu = str.toInt(&converted, 10) - 1;
QWidget::update();
}
}
void VestigeInstrumentView::rolrPreset( void )
{
if ( m_vi->m_plugin != NULL ) {
m_vi->m_plugin->rollPreset( -1 );
bool converted;
QString str = m_vi->m_plugin->presetString().section("/", 0, 0);
if (str != "")
lastPosInMenu = str.toInt(&converted, 10) - 1;
QWidget::update();
}
}
void VestigeInstrumentView::selPreset( void )
{
QAction *action = qobject_cast<QAction *>(sender());
if (action)
if ( m_vi->m_plugin != NULL ) {
lastPosInMenu = action->data().toInt();
m_vi->m_plugin->rollPreset( action->data().toInt() + 2 );
QWidget::update();
}
}
void VestigeInstrumentView::toggleGUI( void )
{
QMutexLocker ml( &m_vi->m_pluginMutex );
@@ -458,6 +769,7 @@ void VestigeInstrumentView::paintEvent( QPaintEvent * )
p.setPen( QColor( 32, 160, 54 ) );
p.drawText( 10, 100, plugin_name );
p.drawText( 10, 211, tr( "Preset" ) );
// m_pluginMutex.lock();
if( m_vi->m_plugin != NULL )
@@ -467,6 +779,7 @@ void VestigeInstrumentView::paintEvent( QPaintEvent * )
p.setFont( pointSize<8>( f ) );
p.drawText( 10, 114, tr( "by" ) + " " +
m_vi->m_plugin->vendorString() );
p.drawText( 10, 225, m_vi->m_plugin->presetString() );
}
// m_pluginMutex.unlock();
}
@@ -474,6 +787,188 @@ void VestigeInstrumentView::paintEvent( QPaintEvent * )
manageVestigeInstrumentView::manageVestigeInstrumentView( Instrument * _instrument,
QWidget * _parent, vestigeInstrument * m_vi2 ) :
InstrumentView( _instrument, _parent )
{
m_vi = m_vi2;
m_vi->m_scrollArea = new QScrollArea( this );
widget = new QWidget(this);
l = new QGridLayout( this );
m_vi->m_subWindow = engine::mainWindow()->workspace()->addSubWindow(new QMdiSubWindow, Qt::SubWindow |
Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowSystemMenuHint);
m_vi->m_subWindow->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
m_vi->m_subWindow->setFixedSize( 960, 300);
m_vi->m_subWindow->setWidget(m_vi->m_scrollArea);
m_vi->m_subWindow->setWindowTitle(m_vi->m_plugin->name());
m_vi->m_subWindow->setWindowIcon( PLUGIN_NAME::getIconPixmap( "logo" ) );
//m_vi->m_subWindow->setAttribute(Qt::WA_DeleteOnClose);
l->setContentsMargins( 20, 10, 10, 10 );
l->setVerticalSpacing( 10 );
l->setHorizontalSpacing( 23 );
m_syncButton = new QPushButton( tr( "VST Sync" ), this );
connect( m_syncButton, SIGNAL( clicked() ), this,
SLOT( syncPlugin() ) );
m_syncButton->setWhatsThis(
tr( "Click here if you want to synchronize all parameters with VST plugin." ) );
l->addWidget( m_syncButton, 0, 0, 1, 2, Qt::AlignLeft );
const QMap<QString, QString> & dump = m_vi->m_plugin->parameterDump();
int paramCount = (dump).size();
bool isVstKnobs = true, isKnobFModel = true;
if (m_vi->vstKnobs == NULL) {
m_vi->vstKnobs = new knob *[paramCount];
isVstKnobs = false;
}
if (m_vi->knobFModel == NULL) {
m_vi->knobFModel = new FloatModel *[paramCount];
isKnobFModel = false;
}
char paramStr[35];
QStringList list1;
if (isVstKnobs == false) {
for (int i = 0; i < paramCount; i++) {
sprintf( paramStr, "param%d", i);
list1 = dump[paramStr].split(":");
m_vi->vstKnobs[i] = new knob( knobBright_26, this );
m_vi->vstKnobs[i]->setHintText( list1.at(1) + ":", "");
m_vi->vstKnobs[i]->setLabel( list1.at(1).left(15) );
sprintf( paramStr, "%d", i);
m_vi->knobFModel[i] = new FloatModel( (list1.at(2)).toFloat(), 0.0f, 1.0f, 0.01f,
castModel<vestigeInstrument>(), tr( paramStr ) );
connect( m_vi->knobFModel[i], SIGNAL( dataChanged() ), this, SLOT( setParameter() ) );
m_vi->vstKnobs[i] ->setModel( m_vi->knobFModel[i] );
}
}
int i = 0;
for (int lrow = 0+1; lrow < (int(paramCount / 10) + 1)+1; lrow++) {
for (int lcolumn = 0; lcolumn < 10; lcolumn++) {
if (i < paramCount)
l->addWidget( m_vi->vstKnobs[i], lrow, lcolumn, Qt::AlignCenter );
i++;
}
}
l->setRowStretch( (int(paramCount / 10) + 1), 1 );
l->setColumnStretch( 10, 1 );
widget->setLayout(l);
widget->setAutoFillBackground(true);
m_vi->m_scrollArea->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOn );
m_vi->m_scrollArea->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
m_vi->m_scrollArea->setPalette( QApplication::palette( m_vi->m_scrollArea ) );
m_vi->m_scrollArea->setMinimumHeight( 64 );
m_vi->m_scrollArea->setWidget( widget );
m_vi->m_subWindow->show();
}
void manageVestigeInstrumentView::syncPlugin( void )
{
char paramStr[35];
QStringList list1;
const QMap<QString, QString> & dump = m_vi->m_plugin->parameterDump();
float f;
for (int i = 0; i<(dump).size(); i++) {
sprintf( paramStr, "param%d", i);
list1 = dump[paramStr].split(":");
f = (list1.at(2)).toFloat();
m_vi->knobFModel[i]->setValue(f);
m_vi->knobFModel[i]->setInitValue(f);
}
}
manageVestigeInstrumentView::~manageVestigeInstrumentView()
{
delete m_vi->m_subWindow;
m_vi->m_subWindow = NULL;
}
void manageVestigeInstrumentView::modelChanged( void )
{
m_vi = castModel<vestigeInstrument>();
}
void manageVestigeInstrumentView::setParameter( void )
{
Model *action = qobject_cast<Model *>(sender());
int knobUNID = action->displayName().toInt();
if ( m_vi->m_plugin != NULL ) {
m_vi->m_plugin->setParam( knobUNID, m_vi->knobFModel[knobUNID]->value() );
}
}
void manageVestigeInstrumentView::dragEnterEvent( QDragEnterEvent * _dee )
{
if( _dee->mimeData()->hasFormat( stringPairDrag::mimeType() ) )
{
QString txt = _dee->mimeData()->data(
stringPairDrag::mimeType() );
if( txt.section( ':', 0, 0 ) == "vstplugin" )
{
_dee->acceptProposedAction();
}
else
{
_dee->ignore();
}
}
else
{
_dee->ignore();
}
}
void manageVestigeInstrumentView::dropEvent( QDropEvent * _de )
{
QString type = stringPairDrag::decodeKey( _de );
QString value = stringPairDrag::decodeValue( _de );
if( type == "vstplugin" )
{
m_vi->loadFile( value );
_de->accept();
return;
}
_de->ignore();
}
void manageVestigeInstrumentView::paintEvent( QPaintEvent * )
{
}

View File

@@ -1,7 +1,7 @@
/*
* vestige.h - instrument VeSTige for hosting VST-plugins
*
* Copyright (c) 2005-2009 Tobias Doerffel <tobydox/at/users.sourceforge.net>
* Copyright (c) 2005-2011 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*
@@ -28,11 +28,15 @@
#include <QtCore/QMutex>
#include <QtGui/QLayout>
#include <QtGui/QMdiSubWindow>
#include <QtGui/QScrollArea>
#include "Instrument.h"
#include "InstrumentView.h"
#include "midi.h"
#include "note.h"
#include "knob.h"
class QPixmap;
@@ -68,6 +72,8 @@ public:
virtual PluginView * instantiateView( QWidget * _parent );
protected slots:
void setParameter( void );
private:
void closePlugin( void );
@@ -79,13 +85,50 @@ private:
QMutex m_pluginMutex;
QString m_pluginDLL;
QMdiSubWindow * m_subWindow;
QScrollArea * m_scrollArea;
FloatModel ** knobFModel;
knob ** vstKnobs;
friend class VestigeInstrumentView;
friend class manageVestigeInstrumentView;
} ;
class manageVestigeInstrumentView : public InstrumentView
{
Q_OBJECT
public:
manageVestigeInstrumentView( Instrument * _instrument, QWidget * _parent, vestigeInstrument * m_vi2 );
virtual ~manageVestigeInstrumentView();
protected slots:
void syncPlugin( void );
void setParameter( void );
protected:
virtual void dragEnterEvent( QDragEnterEvent * _dee );
virtual void dropEvent( QDropEvent * _de );
virtual void paintEvent( QPaintEvent * _pe );
private:
virtual void modelChanged( void );
static QPixmap * s_artwork;
vestigeInstrument * m_vi;
QWidget *widget;
QGridLayout * l;
QPushButton * m_syncButton;
} ;
class VestigeInstrumentView : public InstrumentView
{
@@ -93,10 +136,18 @@ class VestigeInstrumentView : public InstrumentView
public:
VestigeInstrumentView( Instrument * _instrument, QWidget * _parent );
virtual ~VestigeInstrumentView();
manageVestigeInstrumentView * tt;
protected slots:
void updateMenu( void );
void openPlugin( void );
void managePlugin( void );
void openPreset( void );
void savePreset( void );
void rollPreset( void );
void rolrPreset( void );
void selPreset( void );
void toggleGUI( void );
void noteOffAll( void );
@@ -114,8 +165,19 @@ private:
vestigeInstrument * m_vi;
int lastPosInMenu;
pixmapButton * m_openPluginButton;
pixmapButton * m_openPresetButton;
pixmapButton * m_rolLPresetButton;
pixmapButton * m_rolRPresetButton;
QPushButton * m_selPresetButton;
QPushButton * m_toggleGUIButton;
pixmapButton * m_managePluginButton;
pixmapButton * m_savePresetButton;
Instrument * _instrument2;
QWidget * _parent2;
} ;

View File

@@ -163,6 +163,9 @@ public:
// determine product-string of plugin
const char * pluginProductString();
// determine name of plugipn preset
const char * presetName();
// do a complete parameter-dump and post it
void getParameterDump();
@@ -178,6 +181,18 @@ public:
// restore settings chunk of plugin from file
void loadChunkFromFile( const std::string & _file, int _len );
// restore settings chunk of plugin from file
void loadChunkFromPresetFile( const std::string & _file );
// restore settings chunk of plugin from file
void rotateProgram( int _len );
// Load names VST of presets/programs
void loadPrograms( int _len );
// Save presets/programs
void savePreset( const std::string & _file );
// number of inputs
virtual int inputCount() const
{
@@ -386,6 +401,33 @@ bool RemoteVstPlugin::processMessage( const message & _m )
sendMessage( IdLoadSettingsFromFile );
break;
case IdLoadChunkFromPresetFile:
loadChunkFromPresetFile( _m.getString( 0 ) );
sendMessage( IdLoadChunkFromPresetFile );
break;
case IdRotateProgram:
rotateProgram( _m.getInt( 0 ) );
sendMessage( IdRotateProgram );
break;
case IdLoadPrograms:
loadPrograms( _m.getInt( 0 ) );
sendMessage( IdLoadPrograms );
break;
case IdSavePreset:
savePreset( _m.getString( 0 ) );
sendMessage( IdSavePreset );
break;
case IdSetParameter:
m_plugin->setParameter( m_plugin, _m.getInt( 0 ), _m.getFloat( 1 ) );
sendMessage( IdSetParameter );
break;
default:
return RemotePluginClient::processMessage( _m );
}
@@ -726,19 +768,34 @@ const char * RemoteVstPlugin::pluginProductString()
const char * RemoteVstPlugin::presetName()
{
static char buf[32];
buf[0] = 0;
m_plugin->dispatcher(m_plugin, effGetProgramName, 0, 0, buf, 0);
buf[31] = 0;
return buf;
}
void RemoteVstPlugin::getParameterDump()
{
VstParameterProperties vst_props;
message m( IdVstParameterDump );
m.addInt( m_plugin->numParams );
for( int i = 0; i < m_plugin->numParams; ++i )
{
pluginDispatch( effGetParameterProperties, i, 0, &vst_props );
m.addInt( i );
m.addString( vst_props.shortLabel );
m.addFloat( m_plugin->getParameter( m_plugin, i ) );
}
sendMessage( m );
char curPresName[30];
//VstParameterProperties vst_props;
message m( IdVstParameterDump );
m.addInt( m_plugin->numParams );
for( int i = 0; i < m_plugin->numParams; ++i )
{
//pluginDispatch( effGetParameterProperties, i, 0, &vst_props );
m_plugin->dispatcher(m_plugin, effGetParamName, i, 0, curPresName, 0);
m.addInt( i );
m.addString( /*vst_props.shortLabel*/curPresName );
m.addFloat( m_plugin->getParameter( m_plugin, i ) );
}
sendMessage( m );
}
@@ -812,6 +869,257 @@ void RemoteVstPlugin::saveChunkToFile( const std::string & _file )
void RemoteVstPlugin::rotateProgram( int _len )
{
int currProgram;
if (isInitialized() == false) return;
if (_len <= 1) {
currProgram = m_plugin->dispatcher(m_plugin, effGetProgram, 0, 0, 0, 0) + _len;
if (currProgram >= m_plugin->numPrograms) currProgram = m_plugin->numPrograms - 1;
if (currProgram < 0) currProgram = 0;
m_plugin->dispatcher(m_plugin, effSetProgram, 0, currProgram++, 0, 0);
} else {
m_plugin->dispatcher(m_plugin, effSetProgram, 0, _len - 2, 0, 0);
currProgram = _len - 1;
}
char presName[30];
sprintf( presName, " %d/%d: %s", currProgram, m_plugin->numPrograms, presetName() );
sendMessage( message( IdVstPluginPresetString ).addString( presName ) );
}
void RemoteVstPlugin::loadPrograms( int _len )
{
char presName[4096];
char curProgName[30];
if (isInitialized() == false) return;
bool progNameIndexed = (m_plugin->dispatcher(m_plugin, 29, 0, -1, curProgName, 0) == 1);
if (m_plugin->numPrograms > 1) {
if (progNameIndexed) {
for (int i = 0; i< (m_plugin->numPrograms >= 256?256:m_plugin->numPrograms); i++) {
m_plugin->dispatcher(m_plugin, 29, i, -1, curProgName, 0);
if (i == 0) sprintf( presName, "%s", curProgName );
else sprintf( presName + strlen(presName), "|%s", curProgName );
}
} else {
int currProgram = m_plugin->dispatcher(m_plugin, effGetProgram, 0, 0, 0, 0);
for (int i = 0; i< (m_plugin->numPrograms >= 256?256:m_plugin->numPrograms); i++) {
m_plugin->dispatcher(m_plugin, effSetProgram, 0, i, 0, 0);
if (i == 0) sprintf( presName, "%s", presetName() );
else sprintf( presName + strlen(presName), "|%s", presetName() );
}
m_plugin->dispatcher(m_plugin, effSetProgram, 0, currProgram, 0, 0);
}
} else sprintf( presName, "%s", presetName() );
sendMessage( message( IdVstPluginPresetsString ).addString( presName ) );
}
inline unsigned int endian_swap(unsigned int& x)
{
return (x>>24) | ((x<<8) & 0x00FF0000) | ((x>>8) & 0x0000FF00) | (x<<24);
}
struct sBank
{
unsigned int chunkMagic;
unsigned int byteSize;
unsigned int fxMagic;
unsigned int version;
unsigned int fxID;
unsigned int fxVersion;
unsigned int numPrograms;
char prgName[28];
};
void RemoteVstPlugin::savePreset( const std::string & _file )
{
unsigned int chunk_size = 0;
sBank * pBank = ( sBank* ) new char[ sizeof( sBank ) ];
char progName[ 128 ] = { 0 };
char* data = NULL;
const bool chunky = ( m_plugin->flags & ( 1 << 5 ) ) != 0;
bool isPreset = _file.substr( _file.find_last_of( "." ) + 1 ) == "fxp";
int presNameLen = _file.find_last_of( "/" ) + _file.find_last_of( "\\" ) + 2;
if (isPreset) {
for (int i = 0; i < _file.length() - 4 - presNameLen; i++)
progName[i] = i < 23 ? _file[presNameLen + i] : 0;
m_plugin->dispatcher(m_plugin, 4, 0, 0, progName, 0);
} // m_plugin->dispatcher( m_plugin, effGetProgramName, 0, 0, progName, 0.0f );
if ( chunky )
chunk_size = m_plugin->dispatcher( m_plugin, 23, isPreset, 0, &data, false );
else {
if (isPreset) {
chunk_size = m_plugin->numParams * sizeof( float );
data = new char[ chunk_size ];
unsigned int* toUIntArray = reinterpret_cast<unsigned int*>( data );
for ( int i = 0; i < m_plugin->numParams; i++ )
{
float value = m_plugin->getParameter( m_plugin, i );
unsigned int * pValue = ( unsigned int * ) &value;
toUIntArray[ i ] = endian_swap( *pValue );
}
} else chunk_size = (((m_plugin->numParams * sizeof( float )) + 56)*m_plugin->numPrograms);
}
pBank->chunkMagic = 0x4B6E6343;
pBank->byteSize = chunk_size + ( chunky ? sizeof( int ) : 0 ) + 48;
if (!isPreset) pBank->byteSize += 100;
pBank->byteSize = endian_swap( pBank->byteSize );
pBank->fxMagic = chunky ? 0x68435046 : 0x6B437846;
if (!isPreset && chunky) pBank->fxMagic = 0x68434246;
if (!isPreset &&!chunky) pBank->fxMagic = 0x6B427846;
pBank->version = 0x01000000;
unsigned int uIntToFile = (unsigned int) m_plugin->uniqueID;
pBank->fxID = endian_swap( uIntToFile );
uIntToFile = (unsigned int) pluginVersion();
pBank->fxVersion = endian_swap( uIntToFile );
uIntToFile = (unsigned int) chunky ? m_plugin->numPrograms : m_plugin->numParams;
if (!isPreset &&!chunky) uIntToFile = (unsigned int) m_plugin->numPrograms;
pBank->numPrograms = endian_swap( uIntToFile );
FILE * stream = fopen( _file.c_str(), "w" );
fwrite ( pBank, 1, 28, stream );
fwrite ( progName, 1, isPreset ? 28 : 128, stream );
if ( chunky ) {
uIntToFile = endian_swap( chunk_size );
fwrite ( &uIntToFile, 1, 4, stream );
}
if (pBank->fxMagic != 0x6B427846 )
fwrite ( data, 1, chunk_size, stream );
else {
int numPrograms = m_plugin->numPrograms;
int currProgram = m_plugin->dispatcher(m_plugin, effGetProgram, 0, 0, 0, 0);
chunk_size = (m_plugin->numParams * sizeof( float ));
pBank->byteSize = chunk_size + 48;
pBank->byteSize = endian_swap( pBank->byteSize );
pBank->fxMagic = 0x6B437846;
uIntToFile = (unsigned int) m_plugin->numParams;
pBank->numPrograms = endian_swap( uIntToFile );
data = new char[ chunk_size ];
unsigned int* pValue,* toUIntArray = reinterpret_cast<unsigned int*>( data );
float value;
for (int j = 0; j < numPrograms; j++) {
m_plugin->dispatcher(m_plugin, effSetProgram, 0, j, 0, 0);
m_plugin->dispatcher(m_plugin, effGetProgramName, 0, 0, pBank->prgName, 0);
fwrite ( pBank, 1, 56, stream );
for ( int i = 0; i < m_plugin->numParams; i++ )
{
value = m_plugin->getParameter( m_plugin, i );
pValue = ( unsigned int * ) &value;
toUIntArray[ i ] = endian_swap( *pValue );
}
fwrite ( data, 1, chunk_size, stream );
}
m_plugin->dispatcher(m_plugin, effSetProgram, 0, currProgram, 0, 0);
}
fclose( stream );
if ( !chunky )
delete[] data;
delete[] (sBank*)pBank;
}
void RemoteVstPlugin::loadChunkFromPresetFile( const std::string & _file )
{
void * chunk = NULL;
unsigned int * pLen = new unsigned int[ 1 ];
unsigned int len;
sBank * pBank = (sBank*) new char[ sizeof( sBank ) ];
FILE * stream = fopen( _file.c_str(), "r" );
fread ( pBank, 1, 56, stream );
pBank->fxID = endian_swap( pBank->fxID );
pBank->numPrograms = endian_swap( pBank->numPrograms );
unsigned int toUInt;
float * pFloat;
if (m_plugin->uniqueID != pBank->fxID) {
sendMessage( message( IdVstPluginPresetString ).
addString( "Error: Plugin UniqID not match" ) );
fclose( stream );
delete[] (unsigned int*)pLen;
delete[] (sBank*)pBank;
return;
}
if( _file.substr( _file.find_last_of( "." ) + 1 ) != "fxp" )
fseek ( stream , 156 , SEEK_SET );
if(pBank->fxMagic != 0x6B427846) {
if(pBank->fxMagic != 0x6B437846) {
fread (pLen, 1, 4, stream);
chunk = new char[len = endian_swap(*pLen)];
} else chunk = new char[len = sizeof(float)*pBank->numPrograms];
fread (chunk, len, 1, stream);
fclose( stream );
}
if(_file.substr(_file.find_last_of(".") + 1) == "fxp") {
pBank->prgName[23] = 0;
m_plugin->dispatcher(m_plugin, 4, 0, 0, pBank->prgName, 0);
if(pBank->fxMagic != 0x6B437846)
m_plugin->dispatcher(m_plugin, 24, 1, len, chunk, 0);
else {
unsigned int* toUIntArray = reinterpret_cast<unsigned int*>( chunk );
for (int i = 0; i < pBank->numPrograms; i++ ) {
toUInt = endian_swap( toUIntArray[ i ] );
pFloat = ( float* ) &toUInt;
m_plugin->setParameter( m_plugin, i, *pFloat );
}
}
} else {
if(pBank->fxMagic != 0x6B427846) {
m_plugin->dispatcher(m_plugin, 24, 0, len, chunk, 0);
} else {
int numPrograms = pBank->numPrograms;
unsigned int * toUIntArray;
int currProgram = m_plugin->dispatcher(m_plugin, effGetProgram, 0, 0, 0, 0);
chunk = new char[ len = sizeof(float)*m_plugin->numParams ];
toUIntArray = reinterpret_cast<unsigned int *>( chunk );
for (int i =0; i < numPrograms; i++) {
fread (pBank, 1, 56, stream);
fread (chunk, len, 1, stream);
m_plugin->dispatcher(m_plugin, effSetProgram, 0, i, 0, 0);
pBank->prgName[23] = 0;
m_plugin->dispatcher(m_plugin, 4, 0, 0, pBank->prgName, 0);
for (int j = 0; j < m_plugin->numParams; j++ ) {
toUInt = endian_swap( toUIntArray[ j ] );
pFloat = ( float* ) &toUInt;
m_plugin->setParameter( m_plugin, j, *pFloat );
}
}
m_plugin->dispatcher(m_plugin, effSetProgram, 0, currProgram, 0, 0);
fclose( stream );
}
}
char presName[30];
int currProgram = m_plugin->dispatcher(m_plugin, effGetProgram, 0, 0, 0, 0) + 1;
sprintf( presName, " %d/%d: %s", currProgram, m_plugin->numPrograms, presetName() );
sendMessage( message( IdVstPluginPresetString ).addString( presName ) );
delete[] (unsigned int*)pLen;
delete[] (sBank*)pBank;
delete[] (char*)chunk;
}
void RemoteVstPlugin::loadChunkFromFile( const std::string & _file, int _len )
{
char * buf = NULL;

View File

@@ -24,6 +24,7 @@
#include "VstPlugin.h"
#include <QtGui/QFileDialog>
#include <QtCore/QDir>
#include <QtCore/QFileInfo>
#include <QtCore/QLocale>
@@ -86,7 +87,9 @@ VstPlugin::VstPlugin( const QString & _plugin ) :
m_name(),
m_version( 0 ),
m_vendorString(),
m_productString()
m_productString(),
m_presetString(),
m_presetsString()
{
setSplittedChannels( true );
@@ -402,6 +405,14 @@ bool VstPlugin::processMessage( const message & _m )
m_productString = _m.getQString();
break;
case IdVstPluginPresetString:
m_presetString = _m.getQString();
break;
case IdVstPluginPresetsString:
m_presetsString = _m.getQString();
break;
case IdVstPluginUniqueID:
// TODO: display graphically in case of failure
printf("unique ID: %s\n", _m.getString().c_str() );
@@ -420,7 +431,7 @@ bool VstPlugin::processMessage( const message & _m )
item.value = _m.getFloat( ++p );
m_parameterDump["param" + QString::number( item.index )] =
QString::number( item.index ) + ":" +
// QString( item.shortLabel ) + ":" +
/*uncomented*/ /*QString( item.shortLabel )*/ QString::fromStdString(item.shortLabel) + ":" +
QString::number( item.value );
}
break;
@@ -435,6 +446,93 @@ bool VstPlugin::processMessage( const message & _m )
void VstPlugin::openPreset( )
{
QFileDialog ofd( NULL, tr( "Open Preset" ), "",
tr( "Vst Plugin Preset (*.fxp *.fxb)" ) );
ofd.setFileMode( QFileDialog::ExistingFiles );
if( ofd.exec () == QDialog::Accepted &&
!ofd.selectedFiles().isEmpty() )
{
lock();
sendMessage( message( IdLoadChunkFromPresetFile ).
addString(
QSTR_TO_STDSTR(
QDir::toNativeSeparators( ofd.selectedFiles()[0] ) ) )
);
waitForMessage( IdLoadChunkFromPresetFile );
unlock();
}
}
void VstPlugin::rollPreset( int step )
{
lock();
sendMessage( message( IdRotateProgram ).
addInt( step ) );
waitForMessage( IdRotateProgram );
unlock();
}
void VstPlugin::loadPrograms( int step )
{
lock();
sendMessage( message( IdLoadPrograms ).
addInt( step ) );
waitForMessage( IdLoadPrograms );
unlock();
}
void VstPlugin::savePreset( )
{
QString presName = this->presetString() == "" ? tr(": default"): this->presetString();
QFileDialog sfd( NULL, tr( "Save Preset" ), presName.section(": ", 1, 1) + tr(".fxp"),
tr( "Vst Plugin Preset (*.fxp *.fxb)" ) );
sfd.setAcceptMode( QFileDialog::AcceptSave );
sfd.setFileMode( QFileDialog::AnyFile );
if( sfd.exec () == QDialog::Accepted &&
!sfd.selectedFiles().isEmpty() && sfd.selectedFiles()[0] != "" )
{
QString fns = sfd.selectedFiles()[0];
if ((fns.toUpper().indexOf(tr(".FXP")) == -1) && (fns.toUpper().indexOf(tr(".FXB")) == -1))
fns = fns + tr(".fxb");
else fns = fns.left(fns.length() - 4) + (fns.right( 4 )).toLower();
lock();
sendMessage( message( IdSavePreset ).
addString(
QSTR_TO_STDSTR(
QDir::toNativeSeparators( fns ) ) )
);
waitForMessage( IdSavePreset );
unlock();
}
}
void VstPlugin::setParam( int i, float f )
{
lock();
sendMessage( message( IdSetParameter ).addInt( i ).addFloat( f ) );
waitForMessage( IdSetParameter );
unlock();
}
void VstPlugin::loadChunk( const QByteArray & _chunk )
{
QTemporaryFile tf;

View File

@@ -75,6 +75,16 @@ public:
return m_productString;
}
inline const QString & presetString() const
{
return m_presetString;
}
inline const QString & presetsString() const
{
return m_presetsString;
}
const QMap<QString, QString> & parameterDump();
void setParameterDump( const QMap<QString, QString> & _pdump );
@@ -103,6 +113,11 @@ public:
public slots:
void setTempo( bpm_t _bpm );
void updateSampleRate();
void openPreset( void );
void rollPreset( int step );
void loadPrograms( int step );
void savePreset( void );
void setParam( int i, float f );
private:
@@ -120,6 +135,8 @@ private:
Sint32 m_version;
QString m_vendorString;
QString m_productString;
QString m_presetString;
QString m_presetsString;
QMap<QString, QString> m_parameterDump;

View File

@@ -74,6 +74,8 @@ enum VstRemoteMessageIDs
IdVstPluginVersion,
IdVstPluginVendorString,
IdVstPluginProductString,
IdVstPluginPresetString,
IdVstPluginPresetsString,
IdVstPluginUniqueID,
IdVstParameterCount,
IdVstParameterDump,

View File

@@ -67,6 +67,7 @@ private:
friend class VstEffectControls;
friend class VstEffectControlDialog;
friend class manageVSTEffectView;
} ;

View File

@@ -1,7 +1,7 @@
/*
* VstEffectControlDialog.cpp - dialog for displaying VST-effect GUI
*
* Copyright (c) 2006-2010 Tobias Doerffel <tobydox/at/users.sourceforge.net>
* Copyright (c) 2006-2011 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*
@@ -24,20 +24,24 @@
#include <QtGui/QLayout>
#include <QtGui/QMdiArea>
#include <QtGui/QMenu>
#include <QtGui/QPushButton>
#include "VstEffectControlDialog.h"
#include "VstEffect.h"
#include "pixmap_button.h"
#include "tooltip.h"
VstEffectControlDialog::VstEffectControlDialog( VstEffectControls * _ctl ) :
EffectControlDialog( _ctl ),
m_pluginWidget( NULL )
{
QVBoxLayout * l = new QVBoxLayout( this );
l->setMargin( 0 );
l->setSpacing( 0 );
QGridLayout * l = new QGridLayout( this );
l->setContentsMargins( 20, 10, 10, 10 );
l->setVerticalSpacing( 2 );
l->setHorizontalSpacing( 2 );
#ifdef LMMS_BUILD_LINUX
_ctl->m_effect->m_plugin->showEditor();
@@ -47,9 +51,151 @@ VstEffectControlDialog::VstEffectControlDialog( VstEffectControls * _ctl ) :
setWindowTitle( m_pluginWidget->windowTitle() );
QPushButton * btn = new QPushButton( tr( "Show/hide VST FX GUI" ) );
btn->setCheckable( true );
l->addWidget( btn );
l->addWidget( btn, 0, 0, 1, 13, Qt::AlignCenter );
connect( btn, SIGNAL( toggled( bool ) ),
m_pluginWidget, SLOT( setVisible( bool ) ) );
btn->setMinimumWidth( 200 );
btn->setMaximumWidth( 200 );
btn->setMinimumHeight( 24 );
btn->setMaximumHeight( 24 );
m_managePluginButton = new pixmapButton( this, "" );
m_managePluginButton->setCheckable( false );
m_managePluginButton->setCursor( Qt::PointingHandCursor );
m_managePluginButton->setActiveGraphic( PLUGIN_NAME::getIconPixmap(
"track_op_menu" ) );
m_managePluginButton->setInactiveGraphic( PLUGIN_NAME::getIconPixmap(
"track_op_menu" ) );
connect( m_managePluginButton, SIGNAL( clicked() ), _ctl,
SLOT( managePlugin() ) );
toolTip::add( m_managePluginButton, tr( "Control VST-plugin from LMMS host" ) );
m_managePluginButton->setWhatsThis(
tr( "Click here, if you want to control VST-plugin from host." ) );
m_managePluginButton->setMinimumWidth( 21 );
m_managePluginButton->setMaximumWidth( 21 );
m_managePluginButton->setMinimumHeight( 21 );
m_managePluginButton->setMaximumHeight( 21 );
m_openPresetButton = new pixmapButton( this, "" );
m_openPresetButton->setCheckable( false );
m_openPresetButton->setCursor( Qt::PointingHandCursor );
m_openPresetButton->setActiveGraphic( PLUGIN_NAME::getIconPixmap(
"stepper-up-press" ) );
m_openPresetButton->setInactiveGraphic( PLUGIN_NAME::getIconPixmap(
"stepper-up" ) );
connect( m_openPresetButton, SIGNAL( clicked() ), _ctl,
SLOT( openPreset() ) );
toolTip::add( m_openPresetButton, tr( "Open VST-plugin preset" ) );
m_openPresetButton->setWhatsThis(
tr( "Click here, if you want to open another *.fxp, *.fxb VST-plugin preset." ) );
m_openPresetButton->setMinimumWidth( 16 );
m_openPresetButton->setMaximumWidth( 16 );
m_openPresetButton->setMinimumHeight( 16 );
m_openPresetButton->setMaximumHeight( 16 );
m_rolLPresetButton = new pixmapButton( this, "" );
m_rolLPresetButton->setCheckable( false );
m_rolLPresetButton->setCursor( Qt::PointingHandCursor );
m_rolLPresetButton->setActiveGraphic( PLUGIN_NAME::getIconPixmap(
"stepper-left-press" ) );
m_rolLPresetButton->setInactiveGraphic( PLUGIN_NAME::getIconPixmap(
"stepper-left" ) );
connect( m_rolLPresetButton, SIGNAL( clicked() ), _ctl,
SLOT( rolrPreset() ) );
toolTip::add( m_rolLPresetButton, tr( "Previous (-)" ) );
m_rolLPresetButton->setShortcut( Qt::Key_Minus );
m_rolLPresetButton->setWhatsThis(
tr( "Click here, if you want to switch to another VST-plugin presset program." ) );
m_rolLPresetButton->setMinimumWidth( 16 );
m_rolLPresetButton->setMaximumWidth( 16 );
m_rolLPresetButton->setMinimumHeight( 16 );
m_rolLPresetButton->setMaximumHeight( 16 );
m_rolRPresetButton = new pixmapButton( this, "" );
m_rolRPresetButton->setCheckable( false );
m_rolRPresetButton->setCursor( Qt::PointingHandCursor );
m_rolRPresetButton->setActiveGraphic( PLUGIN_NAME::getIconPixmap(
"stepper-right-press" ) );
m_rolRPresetButton->setInactiveGraphic( PLUGIN_NAME::getIconPixmap(
"stepper-right" ) );
connect( m_rolRPresetButton, SIGNAL( clicked() ), _ctl,
SLOT( rollPreset() ) );
toolTip::add( m_rolRPresetButton, tr( "Next (+)" ) );
m_rolRPresetButton->setShortcut( Qt::Key_Plus );
m_rolRPresetButton->setWhatsThis(
tr( "Click here, if you want to switch to another VST-plugin presset program." ) );
m_rolRPresetButton->setMinimumWidth( 16 );
m_rolRPresetButton->setMaximumWidth( 16 );
m_rolRPresetButton->setMinimumHeight( 16 );
m_rolRPresetButton->setMaximumHeight( 16 );
_ctl->m_selPresetButton = new QPushButton( tr( "" ), this );
_ctl->m_selPresetButton->setCheckable( false );
_ctl->m_selPresetButton->setCursor( Qt::PointingHandCursor );
_ctl->m_selPresetButton->setIcon( PLUGIN_NAME::getIconPixmap( "stepper-down" ) );
_ctl->m_selPresetButton->setWhatsThis(
tr( "Click here to select presets that are currently loaded in VST." ) );
_ctl->m_selPresetButton->setMenu(_ctl->menu);
_ctl->m_selPresetButton->setMinimumWidth( 16 );
_ctl->m_selPresetButton->setMaximumWidth( 16 );
_ctl->m_selPresetButton->setMinimumHeight( 16 );
_ctl->m_selPresetButton->setMaximumHeight( 16 );
m_savePresetButton = new pixmapButton( this, "" );
m_savePresetButton->setCheckable( false );
m_savePresetButton->setCursor( Qt::PointingHandCursor );
m_savePresetButton->setActiveGraphic( PLUGIN_NAME::getIconPixmap(
"project_save", 21, 21 ) );
m_savePresetButton->setInactiveGraphic( PLUGIN_NAME::getIconPixmap(
"project_save", 21, 21 ) );
connect( m_savePresetButton, SIGNAL( clicked() ), _ctl,
SLOT( savePreset() ) );
toolTip::add( m_savePresetButton, tr( "Save preset" ) );
m_savePresetButton->setWhatsThis(
tr( "Click here, if you want to save current VST-plugin presset program." ) );
m_savePresetButton->setMinimumWidth( 21 );
m_savePresetButton->setMaximumWidth( 21 );
m_savePresetButton->setMinimumHeight( 21 );
m_savePresetButton->setMaximumHeight( 21 );
l->addWidget( m_openPresetButton, 1, 7, Qt::AlignCenter );
l->addWidget( m_rolLPresetButton, 1, 4, Qt::AlignCenter );
l->addWidget( m_rolRPresetButton, 1, 5, Qt::AlignCenter );
l->addWidget(_ctl->m_selPresetButton, 1, 6, Qt::AlignLeft );
l->addWidget( m_managePluginButton, 1, 10, 2, 2, Qt::AlignLeft );
l->addWidget( m_savePresetButton, 1, 8, 2, 2, Qt::AlignCenter );
l->setRowStretch( 3, 1 );
l->setColumnStretch( 13, 1 );
}
#endif
#ifdef LMMS_BUILD_WIN32
@@ -66,6 +212,14 @@ VstEffectControlDialog::VstEffectControlDialog( VstEffectControls * _ctl ) :
void VstEffectControlDialog::paintEvent( QPaintEvent * )
{
}
VstEffectControlDialog::~VstEffectControlDialog()
{
delete m_pluginWidget;

View File

@@ -27,8 +27,15 @@
#include "EffectControlDialog.h"
#include <QObject>
#include <QPainter>
class VstEffectControls;
class pixmapButton;
class QPixmap;
class QPushButton;
class pixmapButton;
class VstEffectControlDialog : public EffectControlDialog
@@ -37,9 +44,19 @@ public:
VstEffectControlDialog( VstEffectControls * _controls );
virtual ~VstEffectControlDialog();
protected:
virtual void paintEvent( QPaintEvent * _pe );
private:
QWidget * m_pluginWidget;
pixmapButton * m_openPresetButton;
pixmapButton * m_rolLPresetButton;
pixmapButton * m_rolRPresetButton;
pixmapButton * m_selPresetButton;
pixmapButton * m_managePluginButton;
pixmapButton * m_savePresetButton;
} ;
#endif

View File

@@ -27,12 +27,33 @@
#include "VstEffectControls.h"
#include "VstEffect.h"
#include "MainWindow.h"
#include <QtGui/QMdiArea>
#include <QApplication>
VstEffectControls::VstEffectControls( VstEffect * _eff ) :
EffectControls( _eff ),
m_effect( _eff )
m_effect( _eff ),
m_subWindow( NULL ),
knobFModel( NULL ),
vstKnobs( NULL ),
ctrHandle( NULL ),
lastPosInMenu (0)
// m_presetLabel ( NULL )
{
menu = new QMenu;
connect( menu, SIGNAL( aboutToShow() ), this, SLOT( updateMenu() ) );
}
VstEffectControls::~VstEffectControls()
{
delete ctrHandle;
ctrHandle = NULL;
}
@@ -46,6 +67,29 @@ void VstEffectControls::loadSettings( const QDomElement & _this )
if( m_effect->m_plugin != NULL )
{
m_effect->m_plugin->loadSettings( _this );
const QMap<QString, QString> & dump = m_effect->m_plugin->parameterDump();
int paramCount = (dump).size();
char paramStr[35];
vstKnobs = new knob *[paramCount];
knobFModel = new FloatModel *[paramCount];
QStringList list1;
QWidget * xx = new QWidget();
for (int i = 0; i < paramCount; i++) {
sprintf( paramStr, "param%d", i);
list1 = dump[paramStr].split(":");
vstKnobs[i] = new knob( knobBright_26, xx );
vstKnobs[i]->setHintText( list1.at(1) + ":", "");
vstKnobs[i]->setLabel( list1.at(1).left(15) );
knobFModel[i] = new FloatModel( (list1.at(2)).toFloat(), 0.0f, 1.0f, 0.01f, this, QString::number(i) );
knobFModel[i]->loadSettings( _this, paramStr );
connect( knobFModel[i], SIGNAL( dataChanged() ), this, SLOT( setParameter() ) );
vstKnobs[i]->setModel( knobFModel[i] );
}
}
m_effect->m_pluginMutex.unlock();
}
@@ -53,6 +97,20 @@ void VstEffectControls::loadSettings( const QDomElement & _this )
void VstEffectControls::setParameter( void )
{
Model *action = qobject_cast<Model *>(sender());
int knobUNID = action->displayName().toInt();
if ( m_effect->m_plugin != NULL ) {
m_effect->m_plugin->setParam( knobUNID, knobFModel[knobUNID]->value() );
}
}
void VstEffectControls::saveSettings( QDomDocument & _doc, QDomElement & _this )
{
_this.setAttribute( "plugin", m_effect->m_key.attributes["file"] );
@@ -60,6 +118,16 @@ void VstEffectControls::saveSettings( QDomDocument & _doc, QDomElement & _this )
if( m_effect->m_plugin != NULL )
{
m_effect->m_plugin->saveSettings( _doc, _this );
if (knobFModel != NULL) {
const QMap<QString, QString> & dump = m_effect->m_plugin->parameterDump();
int paramCount = (dump).size();
char paramStr[35];
for (int i = 0; i < paramCount; i++)
if (knobFModel[i]->isAutomated() || knobFModel[i]->getControllerConnection()) {
sprintf( paramStr, "param%d", i);
knobFModel[i]->saveSettings( _doc, _this, paramStr );
}
}
}
m_effect->m_pluginMutex.unlock();
}
@@ -75,5 +143,281 @@ int VstEffectControls::controlCount()
void VstEffectControls::managePlugin( void )
{
if ( m_effect->m_plugin != NULL && m_subWindow == NULL ) {
manageVSTEffectView * tt = new manageVSTEffectView( m_effect, this);
ctrHandle = (QObject *)tt;
} else if (m_subWindow != NULL) {
m_scrollArea->show();
m_subWindow->show();
}
}
void VstEffectControls::savePreset( void )
{
if ( m_effect->m_plugin != NULL ) {
m_effect->m_plugin->savePreset( );
/* bool converted;
QString str = m_vi->m_plugin->presetString().section("/", 0, 0);
if (str != "")
lastPosInMenu = str.toInt(&converted, 10) - 1;
QWidget::update();*/
}
}
void VstEffectControls::updateMenu( void )
{
// get all presets -
if ( m_effect->m_plugin != NULL ) {
m_effect->m_plugin->loadPrograms( 1 );
///QWidget::update();
QString str = m_effect->m_plugin->presetsString();
QStringList list1 = str.split("|");
QMenu * to_menu = m_selPresetButton->menu();
to_menu->clear();
QAction *presetActions[list1.size()];
for (int i = 0; i < list1.size(); i++) {
presetActions[i] = new QAction(this);
connect(presetActions[i], SIGNAL(triggered()), this, SLOT(selPreset()));
presetActions[i]->setText(QString("%1. %2").arg(QString::number(i+1), list1.at(i)));
presetActions[i]->setData(i);
if (i == lastPosInMenu) {
presetActions[i]->setIcon(embed::getIconPixmap( "sample_file", 16, 16 ));
} else presetActions[i]->setIcon(embed::getIconPixmap( "edit_copy", 16, 16 ));
to_menu->addAction( presetActions[i] );
}
}
}
void VstEffectControls::openPreset( void )
{
if ( m_effect->m_plugin != NULL ) {
m_effect->m_plugin->openPreset( );
bool converted;
QString str = m_effect->m_plugin->presetString().section("/", 0, 0);
if (str != "")
lastPosInMenu = str.toInt(&converted, 10) - 1;
//QWidget::update();
}
}
void VstEffectControls::rollPreset( void )
{
if ( m_effect->m_plugin != NULL ) {
m_effect->m_plugin->rollPreset( 1 );
bool converted;
QString str = m_effect->m_plugin->presetString().section("/", 0, 0);
if (str != "")
lastPosInMenu = str.toInt(&converted, 10) - 1;
//QWidget::update();
}
}
void VstEffectControls::rolrPreset( void )
{
if ( m_effect->m_plugin != NULL ) {
m_effect->m_plugin->rollPreset( -1 );
bool converted;
QString str = m_effect->m_plugin->presetString().section("/", 0, 0);
if (str != "")
lastPosInMenu = str.toInt(&converted, 10) - 1;
//QWidget::update();
}
}
void VstEffectControls::selPreset( void )
{
QAction *action = qobject_cast<QAction *>(sender());
if (action)
if ( m_effect->m_plugin != NULL ) {
lastPosInMenu = action->data().toInt();
m_effect->m_plugin->rollPreset( lastPosInMenu + 2 );
//QWidget::update();
}
}
void VstEffectControls::paintEvent( QPaintEvent * )
{
}
manageVSTEffectView::manageVSTEffectView( VstEffect * _eff, VstEffectControls * m_vi ) :
m_effect( _eff )
{
m_vi2 = m_vi;
widget = new QWidget();
m_vi->m_scrollArea = new QScrollArea( widget );
l = new QGridLayout( widget );
m_vi->m_subWindow = engine::mainWindow()->workspace()->addSubWindow(new QMdiSubWindow, Qt::SubWindow |
Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowSystemMenuHint);
m_vi->m_subWindow->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
m_vi->m_subWindow->setFixedSize( 960, 300);
m_vi->m_subWindow->setWidget(m_vi->m_scrollArea);
m_vi->m_subWindow->setWindowTitle(_eff->m_plugin->name());
m_vi->m_subWindow->setWindowIcon( PLUGIN_NAME::getIconPixmap( "logo" ) );
//m_vi->m_subWindow->setAttribute(Qt::WA_DeleteOnClose);
l->setContentsMargins( 20, 10, 10, 10 );
l->setVerticalSpacing( 10 );
l->setHorizontalSpacing( 23 );
m_syncButton = new QPushButton( tr( "VST Sync" ), widget );
connect( m_syncButton, SIGNAL( clicked() ), this,
SLOT( syncPlugin() ) );
m_syncButton->setWhatsThis(
tr( "Click here if you want to synchronize all parameters with VST plugin." ) );
l->addWidget( m_syncButton, 0, 0, 1, 2, Qt::AlignLeft );
const QMap<QString, QString> & dump = m_effect->m_plugin->parameterDump();
int paramCount = (dump).size();
bool isVstKnobs = true, isKnobFModel = true;
if (m_vi->vstKnobs == NULL) {
m_vi->vstKnobs = new knob *[paramCount];
isVstKnobs = false;
}
if (m_vi->knobFModel == NULL) {
m_vi->knobFModel = new FloatModel *[paramCount];
isKnobFModel = false;
}
char paramStr[35];
QStringList list1;
if (isVstKnobs == false) {
for (int i = 0; i < paramCount; i++) {
sprintf( paramStr, "param%d", i);
list1 = dump[paramStr].split(":");
m_vi->vstKnobs[i] = new knob( knobBright_26, widget);
m_vi->vstKnobs[i]->setHintText( list1.at(1) + ":", "");
m_vi->vstKnobs[i]->setLabel( list1.at(1).left(15) );
sprintf( paramStr, "%d", i);
m_vi->knobFModel[i] = new FloatModel( (list1.at(2)).toFloat(), 0.0f, 1.0f, 0.01f,
_eff, tr( paramStr ) );
connect( m_vi->knobFModel[i], SIGNAL( dataChanged() ), this, SLOT( setParameter() ) );
m_vi->vstKnobs[i] ->setModel( m_vi->knobFModel[i] );
}
}
int i = 0;
for (int lrow = 0+1; lrow < (int(paramCount / 10) + 1)+1; lrow++) {
for (int lcolumn = 0; lcolumn < 10; lcolumn++) {
if (i < paramCount)
l->addWidget( m_vi->vstKnobs[i], lrow, lcolumn, Qt::AlignCenter );
i++;
}
}
l->setRowStretch( (int(paramCount / 10) + 1), 1 );
l->setColumnStretch( 10, 1 );
widget->setLayout(l);
widget->setAutoFillBackground(true);
m_vi->m_scrollArea->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOn );
m_vi->m_scrollArea->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
m_vi->m_scrollArea->setPalette( QApplication::palette( m_vi->m_scrollArea ) );
m_vi->m_scrollArea->setMinimumHeight( 64 );
m_vi->m_scrollArea->setWidget( widget );
m_vi->m_subWindow->show();
}
void manageVSTEffectView::syncPlugin( void )
{
char paramStr[35];
QStringList list1;
const QMap<QString, QString> & dump = m_effect->m_plugin->parameterDump();
float f;
for (int i = 0; i<(dump).size(); i++) {
sprintf( paramStr, "param%d", i);
list1 = dump[paramStr].split(":");
f = (list1.at(2)).toFloat();
m_vi2->knobFModel[i]->setValue(f);
m_vi2->knobFModel[i]->setInitValue(f);
}
}
void manageVSTEffectView::setParameter( void )
{
Model *action = qobject_cast<Model *>(sender());
int knobUNID = action->displayName().toInt();
if ( m_effect->m_plugin != NULL ) {
m_effect->m_plugin->setParam( knobUNID, m_vi2->knobFModel[knobUNID]->value() );
}
}
manageVSTEffectView::~manageVSTEffectView()
{
delete m_vi2->m_subWindow;
m_vi2->m_subWindow = NULL;
}
#include "moc_VstEffectControls.cxx"

View File

@@ -28,6 +28,17 @@
#include "EffectControls.h"
#include "VstEffectControlDialog.h"
#include <QtGui/QMenu>
#include "embed.h"
#include <QtGui/QPushButton>
#include <QtGui/QMdiSubWindow>
#include <QtGui/QScrollArea>
#include "knob.h"
#include <QtGui/QLayout>
#include <QPainter>
#include <QObject>
class VstEffect;
@@ -37,9 +48,7 @@ class VstEffectControls : public EffectControls
Q_OBJECT
public:
VstEffectControls( VstEffect * _eff );
virtual ~VstEffectControls()
{
}
virtual ~VstEffectControls();
virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent );
virtual void loadSettings( const QDomElement & _this );
@@ -56,10 +65,70 @@ public:
}
protected slots:
void updateMenu( void );
void openPlugin( void );
void managePlugin( void );
void openPreset( void );
void savePreset( void );
void rollPreset( void );
void rolrPreset( void );
void selPreset( void );
void setParameter( void );
protected:
virtual void paintEvent( QPaintEvent * _pe );
private:
VstEffect * m_effect;
QPushButton * m_selPresetButton;
QMenu *menu;
QMdiSubWindow * m_subWindow;
QScrollArea * m_scrollArea;
FloatModel ** knobFModel;
knob ** vstKnobs;
QObject * ctrHandle;
int lastPosInMenu;
// QLabel * m_presetLabel;
friend class VstEffectControlDialog;
friend class manageVSTEffectView;
} ;
class manageVSTEffectView : public QObject
{
Q_OBJECT
public:
manageVSTEffectView( VstEffect * _eff, VstEffectControls * m_vi );
virtual ~manageVSTEffectView();
protected slots:
void syncPlugin( void );
void setParameter( void );
private:
// static QPixmap * s_artwork;
VstEffectControls * m_vi2;
VstEffect * m_effect;
QWidget *widget;
QGridLayout * l;
QPushButton * m_syncButton;
} ;