From 4d645b335d560aae0e7620243b021cb283e0ba99 Mon Sep 17 00:00:00 2001 From: quadro Date: Sat, 22 Oct 2011 20:14:28 +0200 Subject: [PATCH] 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 --- data/themes/default/stepper-down-press.png | Bin 0 -> 510 bytes data/themes/default/stepper-down.png | Bin 0 -> 516 bytes data/themes/default/stepper-left-press.png | Bin 0 -> 514 bytes data/themes/default/stepper-left.png | Bin 0 -> 548 bytes data/themes/default/stepper-right-press.png | Bin 0 -> 519 bytes data/themes/default/stepper-right.png | Bin 0 -> 491 bytes data/themes/default/stepper-up-press.png | Bin 0 -> 516 bytes data/themes/default/stepper-up.png | Bin 0 -> 528 bytes include/RemotePlugin.h | 5 + include/aeffectx.h | 21 +- plugins/vestige/vestige.cpp | 505 +++++++++++++++++- plugins/vestige/vestige.h | 64 ++- plugins/vst_base/RemoteVstPlugin.cpp | 330 +++++++++++- plugins/vst_base/VstPlugin.cpp | 102 +++- plugins/vst_base/VstPlugin.h | 17 + plugins/vst_base/communication.h | 2 + plugins/vst_effect/VstEffect.h | 1 + plugins/vst_effect/VstEffectControlDialog.cpp | 166 +++++- plugins/vst_effect/VstEffectControlDialog.h | 17 + plugins/vst_effect/VstEffectControls.cpp | 346 +++++++++++- plugins/vst_effect/VstEffectControls.h | 75 ++- 21 files changed, 1620 insertions(+), 31 deletions(-) create mode 100644 data/themes/default/stepper-down-press.png create mode 100644 data/themes/default/stepper-down.png create mode 100644 data/themes/default/stepper-left-press.png create mode 100644 data/themes/default/stepper-left.png create mode 100644 data/themes/default/stepper-right-press.png create mode 100644 data/themes/default/stepper-right.png create mode 100644 data/themes/default/stepper-up-press.png create mode 100644 data/themes/default/stepper-up.png diff --git a/data/themes/default/stepper-down-press.png b/data/themes/default/stepper-down-press.png new file mode 100644 index 0000000000000000000000000000000000000000..c1cec54a3a70ae07f374f3b9fedb77abbcba327c GIT binary patch literal 510 zcmVPx#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iXS+ z4;v7P5a=EN00DkUL_t(I%Z-w;j?-Wegunf5EK9a5S&;~_j-FFeMN#56q~;lTnpnD; zM>wTOlR$IWI~2bi2;{=8|9;3Qj6%l%*@Czst-n zZ)VYgq&Q%*E`ht>1&g(K!UDT?9;@E-U8 zB>ytrtQX)3_>vSw@dSJamgAte)HmSs;c)o+3u{vm`tdD*C;$Ke07*qoM6N<$g18CR ABLDyZ literal 0 HcmV?d00001 diff --git a/data/themes/default/stepper-down.png b/data/themes/default/stepper-down.png new file mode 100644 index 0000000000000000000000000000000000000000..b7b8e2f1a3b63ef6f2fb94ec16c58b6237d7baa5 GIT binary patch literal 516 zcmV+f0{i`mP)l&X6otR{?6}S1fm#(U0~-TKsl-31T8SOO!mr8Jxxb-O zls}WXLnKg^R2eD;sMI?6oDQ}jAyn$!o_)Xb&b{Y_kDorf{QZZrEGZvLcDqNgIaO(T z##xpT2xM7C_WBi3GQt?w;6Gph+t_utFp`Oquml#iP5?eSQ};?pB5ehvw%IRC97J6A zhHwzDgqoY`3Bn5}03ifyBa29^8HrRDmiKn0>Ld&xiRgM?RwHH!BV++)GMP{m1tA1N z2*elxD2jr~WU>cMJ$l^FFJWLb8Zn#A$n(5$B=S6GI-N2c4r`}RnB?92-lbHbs=_v_ z)r#?W%y2m5{{Egk&zaBXoS&a_eSOV#y9FS|NQjYeaq+=Y9if`dcDr2`iv|6DAAq~N zJFc#-czAdqNs?wSkr*RMQ52Ug*v7TlY*;Rr^m;wk>-8S4_Y#q+CTbG~gMpJIc_#2Y z`$H0~fGuK-R8`eHBzqrK3%2LuR~bV6f4AFVn-utA`wft_jcJ-bb9C&c`BnlylTN4e z3wR53f#fN03T&zbZh)^zr_;Fsw!o+n`k(p^e7U{7{q`5vMr7B%ZbS_L0000Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FTR01FTSts}j400007bV*G`2iXS+ z4;%>9J?4)900DwYL_t(I%Z-ykj@m#FMc=PBNC@E#kX(Y55bz!N0X#_}gn(Hf%Q7TDhNRvy zWWod)@D=z5OeJAvxPyD7jV(gR93j#pWI|Cygo>hg170Kz03-omX5F{U5>NobOhC$I zz$?9QcO>ENf6v+$Is%AMS8`!};5|{E=d4yM7K;Tjwzxa)PK=SZZE0hh2yS=32bX2Z z`Fv)x**yFS?qrV?bmB1I`O}-N6ckeGM!FYuh$%pN8StL6LIUty99j| zP1CU3?N~0Cj7FobGoMy)I2@?!n!#W|RaHzTlg@=765NXR`#nw5FdPn<&*xq4W@WQL z2muvE;eB9A>W=Vg-`ie>uC_Md7jW)1ml)$eY7)5TzAG3YjK|~Oz%wwD6w(YN6?UCU z3zlZX(%V8>!2;QKyZt$v&AtH7?*0^GOm|Z%_-LH}0GvL7SC7|rV*mgE07*qoM6N<$ Ef|VcCm;e9( literal 0 HcmV?d00001 diff --git a/data/themes/default/stepper-left.png b/data/themes/default/stepper-left.png new file mode 100644 index 0000000000000000000000000000000000000000..7f2278056f304edd41647e3844f8a56bfca969bd GIT binary patch literal 548 zcmV+<0^9wGP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FTR01FTSts}j400007bV*G`2iXP_ z4>C7um|WEW00E>)L_t(I%bk-wjv7G_g}+zTc#+7k5IDlYAScea0%x#*!0Cp&2e53P z21q#wnIj@n$RI#qX1X2B@Uz}UvRqQDM^o>;s#4cemSqASf$zWvGox0k;U0MR@PJ9k z44Gl7?#mGY_yT+d-b=#Wi7_EX^8AEU0)-*dOF>G3Z@?!>HA%!6kwi)&Kb=rTFj@I6 zVJ48FO5ig$kx~M<2qB>uDNrRqbsI?7E%8h~3$)v9o}Zo=3fb{ z?RJ^Z=WMszSEO64@ed*CZqA#{=Fh)@tJR8bw@a2~ESF1;$Kxe;e#$pHNGTzS&1S=7 zGNE3tGa8L(wOX%;cSkq_*XuR2*^EY`LBHQG!DhHSW{!Ixgc{1SEZq{#95drwOy>=> zDqs1bTqwhUU%>C{80E5DMX5Y+U1zJvLU^;;+yEbeHsJ1F8ORBhD?@PH0v?>;j)#DU mK=6Q4O7wcYN8rc**!d6kERZhDB>@uv0000`{j86 literal 0 HcmV?d00001 diff --git a/data/themes/default/stepper-right-press.png b/data/themes/default/stepper-right-press.png new file mode 100644 index 0000000000000000000000000000000000000000..ad634e175be21533ba581c7b3bb0334508b00a18 GIT binary patch literal 519 zcmV+i0{H!jP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iXS+ z4;>FuLPBi-00Dm&=9SZpU;wB~876mStDDwhQ+jcr+TZTCM2!`)oEF@;tu+$LqzIyUaulC)jv0nf1@Ig^PQDsC;bZ@46F0Jo+y&nIPa`$FBBqi{}Ip^Xq8FMpC z#?~_T9%C$>P7B~W@Wr{lBaXAZ8D~>Zp@J~R<9*!w5%>nYyaMwuI~f%~VUPd-002ov JPDHLkV1n0e+zbE! literal 0 HcmV?d00001 diff --git a/data/themes/default/stepper-right.png b/data/themes/default/stepper-right.png new file mode 100644 index 0000000000000000000000000000000000000000..215e88f6c940dcc87899ba606f3d7407c9351272 GIT binary patch literal 491 zcmVRgiKVxexih@>v;;U6? zRV#913_zl)Bj8J81n=?AF&^LZ@bH;5 zO$i|&5^5C{DL~}CBLt5~C>sTU)oR7@cqGd*(losR)&wsLRpWlYC(m)EBO{!0grLge#>jmS%RP{ hI9H$j7w`@E{u@dTlWXeT!gv4x002ovPDHLkV1gID(Psbv literal 0 HcmV?d00001 diff --git a/data/themes/default/stepper-up-press.png b/data/themes/default/stepper-up-press.png new file mode 100644 index 0000000000000000000000000000000000000000..99f47711fdc757b7e4d9d9b8a1f19feef2f64e97 GIT binary patch literal 516 zcmV+f0{i`mP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iXS+ z4;?ppK>G6l00D$aL_t(I%axKb&eKp3gumIB{9T*^*=hX)B}F78%lF^_lw5;?lTdOJ zD@u`q3#1_xvXshl^t=?$@t;ISKdfZw*`9ejv$Jw{Hk-{S;4AQff2*IsH{gegqWA)Q z20j8$b7)Bbxcl|f1=s`MRTRZ9;EklG2hc>ko`+$$y{rd*t0)S;1^!RDI}1se+1Oct z->LYUrK_Sv2!Vum%)~G_l31-)R8zX{z$@84L zu34|wQ+G2PIRTaBv&SJa#E83-Wf@gfak*SL91Z|%w_BFW<((1>fnWiXKxn$Xsw(=v zr)e76wxw-bnx>)e`^i!=AS75IL*~d0ADq+a#PN8f>$+*UUDvVS?LV7HO6e9wq1d%imANM20H)56E7m~&qq@QzJII{`k41`I^ zkBy!{uP%|9kO|4Kba+wl+FHM0b<_A7$F^YyQN7Q%#00001#&5QV=p_bzfnLkdik1R+6}E39Ho#Gb3ghF=m)aNLCRTqtS@%cFTA?X1QFlTrL@p$85J- zMxzlNX$_MIFJ8X7c2A^gXw7Dm`FzfLy~fM{xV^n)u~-me0+3X8)g(v!DvA63YN$%wKtizEyqovezQfg@Fy zDIqhWnISXGMDlXK_1mu>k(sKV2L{Lx>5=#`MWwwr5Js7wD&s$^ + * Copyright (c) 2005-2011 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -29,6 +29,8 @@ #include #include #include +#include +#include #include #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 & 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(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 & 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(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 & 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(), 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 & 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(); +} + + + +void manageVestigeInstrumentView::setParameter( void ) +{ + + Model *action = qobject_cast(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 * ) +{ +} diff --git a/plugins/vestige/vestige.h b/plugins/vestige/vestige.h index 1b8242b54..bed73ada7 100644 --- a/plugins/vestige/vestige.h +++ b/plugins/vestige/vestige.h @@ -1,7 +1,7 @@ /* * vestige.h - instrument VeSTige for hosting VST-plugins * - * Copyright (c) 2005-2009 Tobias Doerffel + * Copyright (c) 2005-2011 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -28,11 +28,15 @@ #include +#include +#include +#include #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; } ; diff --git a/plugins/vst_base/RemoteVstPlugin.cpp b/plugins/vst_base/RemoteVstPlugin.cpp index 3bb167252..2f17643d9 100644 --- a/plugins/vst_base/RemoteVstPlugin.cpp +++ b/plugins/vst_base/RemoteVstPlugin.cpp @@ -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( 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( 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( 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( 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; diff --git a/plugins/vst_base/VstPlugin.cpp b/plugins/vst_base/VstPlugin.cpp index d5414f7ff..289686185 100644 --- a/plugins/vst_base/VstPlugin.cpp +++ b/plugins/vst_base/VstPlugin.cpp @@ -24,6 +24,7 @@ #include "VstPlugin.h" +#include #include #include #include @@ -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; diff --git a/plugins/vst_base/VstPlugin.h b/plugins/vst_base/VstPlugin.h index fc48f021c..97a7d67e6 100644 --- a/plugins/vst_base/VstPlugin.h +++ b/plugins/vst_base/VstPlugin.h @@ -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 & parameterDump(); void setParameterDump( const QMap & _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 m_parameterDump; diff --git a/plugins/vst_base/communication.h b/plugins/vst_base/communication.h index 4012ef40f..542a4d142 100644 --- a/plugins/vst_base/communication.h +++ b/plugins/vst_base/communication.h @@ -74,6 +74,8 @@ enum VstRemoteMessageIDs IdVstPluginVersion, IdVstPluginVendorString, IdVstPluginProductString, + IdVstPluginPresetString, + IdVstPluginPresetsString, IdVstPluginUniqueID, IdVstParameterCount, IdVstParameterDump, diff --git a/plugins/vst_effect/VstEffect.h b/plugins/vst_effect/VstEffect.h index 5fdcfa224..4c11bbbcc 100644 --- a/plugins/vst_effect/VstEffect.h +++ b/plugins/vst_effect/VstEffect.h @@ -67,6 +67,7 @@ private: friend class VstEffectControls; friend class VstEffectControlDialog; + friend class manageVSTEffectView; } ; diff --git a/plugins/vst_effect/VstEffectControlDialog.cpp b/plugins/vst_effect/VstEffectControlDialog.cpp index a6c83b758..36fc411c9 100644 --- a/plugins/vst_effect/VstEffectControlDialog.cpp +++ b/plugins/vst_effect/VstEffectControlDialog.cpp @@ -1,7 +1,7 @@ /* * VstEffectControlDialog.cpp - dialog for displaying VST-effect GUI * - * Copyright (c) 2006-2010 Tobias Doerffel + * Copyright (c) 2006-2011 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -24,20 +24,24 @@ #include #include +#include #include #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; diff --git a/plugins/vst_effect/VstEffectControlDialog.h b/plugins/vst_effect/VstEffectControlDialog.h index 84e007062..bd4687511 100644 --- a/plugins/vst_effect/VstEffectControlDialog.h +++ b/plugins/vst_effect/VstEffectControlDialog.h @@ -27,8 +27,15 @@ #include "EffectControlDialog.h" +#include +#include + 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 diff --git a/plugins/vst_effect/VstEffectControls.cpp b/plugins/vst_effect/VstEffectControls.cpp index da910f38d..0e2da3c61 100644 --- a/plugins/vst_effect/VstEffectControls.cpp +++ b/plugins/vst_effect/VstEffectControls.cpp @@ -27,12 +27,33 @@ #include "VstEffectControls.h" #include "VstEffect.h" +#include "MainWindow.h" +#include +#include + 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 & 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(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 & 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(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 & 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 & 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(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" diff --git a/plugins/vst_effect/VstEffectControls.h b/plugins/vst_effect/VstEffectControls.h index 179593de0..06ae7b14c 100644 --- a/plugins/vst_effect/VstEffectControls.h +++ b/plugins/vst_effect/VstEffectControls.h @@ -28,6 +28,17 @@ #include "EffectControls.h" #include "VstEffectControlDialog.h" +#include +#include "embed.h" +#include + +#include +#include +#include "knob.h" +#include +#include +#include + 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; } ;