VstPlugin.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799
  1. /*
  2. * VstPlugin.cpp - implementation of VstPlugin class
  3. *
  4. * Copyright (c) 2005-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
  5. *
  6. * This file is part of LMMS - https://lmms.io
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public
  10. * License as published by the Free Software Foundation; either
  11. * version 2 of the License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public
  19. * License along with this program (see COPYING); if not, write to the
  20. * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  21. * Boston, MA 02110-1301 USA.
  22. *
  23. */
  24. #include "VstPlugin.h"
  25. #include "communication.h"
  26. #include <QtCore/QtEndian>
  27. #include <QtCore/QDebug>
  28. #include <QDir>
  29. #include <QFileInfo>
  30. #include <QLocale>
  31. #include <QTemporaryFile>
  32. #include <QCloseEvent>
  33. #include <QMdiArea>
  34. #include <QMdiSubWindow>
  35. #ifdef LMMS_BUILD_LINUX
  36. # include <QX11Info>
  37. # include "X11EmbedContainer.h"
  38. #endif
  39. #include <QWindow>
  40. #include <QDomDocument>
  41. #ifdef LMMS_BUILD_WIN32
  42. # include <windows.h>
  43. # include <QLayout>
  44. #endif
  45. #include "ConfigManager.h"
  46. #include "GuiApplication.h"
  47. #include "LocaleHelper.h"
  48. #include "MainWindow.h"
  49. #include "Mixer.h"
  50. #include "PathUtil.h"
  51. #include "Song.h"
  52. #include "FileDialog.h"
  53. #ifdef LMMS_BUILD_LINUX
  54. # include <X11/Xlib.h>
  55. #endif
  56. namespace PE
  57. {
  58. // Utilities for reading PE file machine type
  59. // See specification at https://msdn.microsoft.com/library/windows/desktop/ms680547(v=vs.85).aspx
  60. // Work around name conflict
  61. #ifdef i386
  62. # undef i386
  63. #endif
  64. enum class MachineType : uint16_t
  65. {
  66. unknown = 0x0,
  67. amd64 = 0x8664,
  68. i386 = 0x14c,
  69. };
  70. class FileInfo
  71. {
  72. public:
  73. FileInfo(QString filePath)
  74. : m_file(filePath)
  75. {
  76. m_file.open(QFile::ReadOnly);
  77. m_map = m_file.map(0, m_file.size());
  78. if (m_map == nullptr) {
  79. throw std::runtime_error("Cannot map file");
  80. }
  81. }
  82. ~FileInfo()
  83. {
  84. m_file.unmap(m_map);
  85. }
  86. MachineType machineType()
  87. {
  88. int32_t peOffset = qFromLittleEndian(* reinterpret_cast<int32_t*>(m_map + 0x3C));
  89. uchar* peSignature = m_map + peOffset;
  90. if (memcmp(peSignature, "PE\0\0", 4)) {
  91. throw std::runtime_error("Invalid PE file");
  92. }
  93. uchar * coffHeader = peSignature + 4;
  94. uint16_t machineType = qFromLittleEndian(* reinterpret_cast<uint16_t*>(coffHeader));
  95. return static_cast<MachineType>(machineType);
  96. }
  97. private:
  98. QFile m_file;
  99. uchar* m_map;
  100. };
  101. }
  102. VstPlugin::VstPlugin( const QString & _plugin ) :
  103. m_plugin( PathUtil::toAbsolute(_plugin) ),
  104. m_pluginWindowID( 0 ),
  105. m_embedMethod( gui
  106. ? ConfigManager::inst()->vstEmbedMethod()
  107. : "headless" ),
  108. m_version( 0 ),
  109. m_currentProgram()
  110. {
  111. setSplittedChannels( true );
  112. PE::MachineType machineType;
  113. try {
  114. PE::FileInfo peInfo(m_plugin);
  115. machineType = peInfo.machineType();
  116. } catch (std::runtime_error& e) {
  117. qCritical() << "Error while determining PE file's machine type: " << e.what();
  118. machineType = PE::MachineType::unknown;
  119. }
  120. switch(machineType)
  121. {
  122. case PE::MachineType::amd64:
  123. tryLoad( REMOTE_VST_PLUGIN_FILEPATH_64 ); // Default: RemoteVstPlugin64
  124. break;
  125. case PE::MachineType::i386:
  126. tryLoad( REMOTE_VST_PLUGIN_FILEPATH_32 ); // Default: 32/RemoteVstPlugin32
  127. break;
  128. default:
  129. m_failed = true;
  130. return;
  131. }
  132. setTempo( Engine::getSong()->getTempo() );
  133. connect( Engine::getSong(), SIGNAL( tempoChanged( bpm_t ) ),
  134. this, SLOT( setTempo( bpm_t ) ), Qt::DirectConnection );
  135. connect( Engine::mixer(), SIGNAL( sampleRateChanged() ),
  136. this, SLOT( updateSampleRate() ) );
  137. // update once per second
  138. m_idleTimer.start( 1000 );
  139. connect( &m_idleTimer, SIGNAL( timeout() ),
  140. this, SLOT( idleUpdate() ) );
  141. }
  142. VstPlugin::~VstPlugin()
  143. {
  144. delete m_pluginWidget;
  145. }
  146. void VstPlugin::tryLoad( const QString &remoteVstPluginExecutable )
  147. {
  148. init( remoteVstPluginExecutable, false, {m_embedMethod} );
  149. waitForHostInfoGotten();
  150. if( failed() )
  151. {
  152. return;
  153. }
  154. lock();
  155. VstHostLanguages hlang = LanguageEnglish;
  156. switch( QLocale::system().language() )
  157. {
  158. case QLocale::French: hlang = LanguageFrench; break;
  159. case QLocale::German: hlang = LanguageGerman; break;
  160. case QLocale::Italian: hlang = LanguageItalian; break;
  161. case QLocale::Japanese: hlang = LanguageJapanese; break;
  162. case QLocale::Korean: hlang = LanguageKorean; break;
  163. case QLocale::Spanish: hlang = LanguageSpanish; break;
  164. default: break;
  165. }
  166. sendMessage( message( IdVstSetLanguage ).addInt( hlang ) );
  167. sendMessage( message( IdVstLoadPlugin ).addString( QSTR_TO_STDSTR( m_plugin ) ) );
  168. waitForInitDone();
  169. unlock();
  170. }
  171. void VstPlugin::loadSettings( const QDomElement & _this )
  172. {
  173. if( _this.hasAttribute( "program" ) )
  174. {
  175. setProgram( _this.attribute( "program" ).toInt() );
  176. }
  177. const int num_params = _this.attribute( "numparams" ).toInt();
  178. // if it exists try to load settings chunk
  179. if( _this.hasAttribute( "chunk" ) )
  180. {
  181. loadChunk( QByteArray::fromBase64(
  182. _this.attribute( "chunk" ).toUtf8() ) );
  183. }
  184. else if( num_params > 0 )
  185. {
  186. // no chunk, restore individual parameters
  187. QMap<QString, QString> dump;
  188. for( int i = 0; i < num_params; ++i )
  189. {
  190. const QString key = "param" +
  191. QString::number( i );
  192. dump[key] = _this.attribute( key );
  193. }
  194. setParameterDump( dump );
  195. }
  196. }
  197. void VstPlugin::saveSettings( QDomDocument & _doc, QDomElement & _this )
  198. {
  199. if ( m_embedMethod != "none" )
  200. {
  201. if( pluginWidget() != NULL )
  202. {
  203. _this.setAttribute( "guivisible", pluginWidget()->isVisible() );
  204. }
  205. }
  206. else
  207. {
  208. int visible = isUIVisible();
  209. if ( visible != -1 )
  210. {
  211. _this.setAttribute( "guivisible", visible );
  212. }
  213. }
  214. // try to save all settings in a chunk
  215. QByteArray chunk = saveChunk();
  216. if( !chunk.isEmpty() )
  217. {
  218. _this.setAttribute( "chunk", QString( chunk.toBase64() ) );
  219. }
  220. else
  221. {
  222. // plugin doesn't seem to support chunks, therefore save
  223. // individual parameters
  224. const QMap<QString, QString> & dump = parameterDump();
  225. _this.setAttribute( "numparams", dump.size() );
  226. for( QMap<QString, QString>::const_iterator it = dump.begin();
  227. it != dump.end(); ++it )
  228. {
  229. _this.setAttribute( it.key(), it.value() );
  230. }
  231. }
  232. _this.setAttribute( "program", currentProgram() );
  233. }
  234. void VstPlugin::toggleUI()
  235. {
  236. if ( m_embedMethod == "none" )
  237. {
  238. RemotePlugin::toggleUI();
  239. }
  240. else if (pluginWidget())
  241. {
  242. toggleEditorVisibility();
  243. }
  244. }
  245. void VstPlugin::setTempo( bpm_t _bpm )
  246. {
  247. lock();
  248. sendMessage( message( IdVstSetTempo ).addInt( _bpm ) );
  249. unlock();
  250. }
  251. void VstPlugin::updateSampleRate()
  252. {
  253. lock();
  254. sendMessage( message( IdSampleRateInformation ).
  255. addInt( Engine::mixer()->processingSampleRate() ) );
  256. waitForMessage( IdInformationUpdated, true );
  257. unlock();
  258. }
  259. int VstPlugin::currentProgram()
  260. {
  261. lock();
  262. sendMessage( message( IdVstCurrentProgram ) );
  263. waitForMessage( IdVstCurrentProgram, true );
  264. unlock();
  265. return m_currentProgram;
  266. }
  267. const QMap<QString, QString> & VstPlugin::parameterDump()
  268. {
  269. lock();
  270. sendMessage( IdVstGetParameterDump );
  271. waitForMessage( IdVstParameterDump, true );
  272. unlock();
  273. return m_parameterDump;
  274. }
  275. void VstPlugin::setParameterDump( const QMap<QString, QString> & _pdump )
  276. {
  277. message m( IdVstSetParameterDump );
  278. m.addInt( _pdump.size() );
  279. for( QMap<QString, QString>::ConstIterator it = _pdump.begin();
  280. it != _pdump.end(); ++it )
  281. {
  282. const VstParameterDumpItem item =
  283. {
  284. ( *it ).section( ':', 0, 0 ).toInt(),
  285. "",
  286. LocaleHelper::toFloat((*it).section(':', 2, -1))
  287. } ;
  288. m.addInt( item.index );
  289. m.addString( item.shortLabel );
  290. m.addFloat( item.value );
  291. }
  292. lock();
  293. sendMessage( m );
  294. unlock();
  295. }
  296. QWidget *VstPlugin::pluginWidget()
  297. {
  298. return m_pluginWidget;
  299. }
  300. bool VstPlugin::processMessage( const message & _m )
  301. {
  302. switch( _m.id )
  303. {
  304. case IdVstPluginWindowID:
  305. m_pluginWindowID = _m.getInt();
  306. if( m_embedMethod == "none"
  307. && ConfigManager::inst()->value(
  308. "ui", "vstalwaysontop" ).toInt() )
  309. {
  310. #ifdef LMMS_BUILD_WIN32
  311. // We're changing the owner, not the parent,
  312. // so this is legal despite MSDN's warning
  313. SetWindowLongPtr( (HWND)(intptr_t) m_pluginWindowID,
  314. GWLP_HWNDPARENT,
  315. (LONG_PTR) gui->mainWindow()->winId() );
  316. #endif
  317. #ifdef LMMS_BUILD_LINUX
  318. XSetTransientForHint( QX11Info::display(),
  319. m_pluginWindowID,
  320. gui->mainWindow()->winId() );
  321. #endif
  322. }
  323. break;
  324. case IdVstPluginEditorGeometry:
  325. m_pluginGeometry = QSize( _m.getInt( 0 ),
  326. _m.getInt( 1 ) );
  327. break;
  328. case IdVstPluginName:
  329. m_name = _m.getQString();
  330. break;
  331. case IdVstPluginVersion:
  332. m_version = _m.getInt();
  333. break;
  334. case IdVstPluginVendorString:
  335. m_vendorString = _m.getQString();
  336. break;
  337. case IdVstPluginProductString:
  338. m_productString = _m.getQString();
  339. break;
  340. case IdVstCurrentProgram:
  341. m_currentProgram = _m.getInt();
  342. break;
  343. case IdVstCurrentProgramName:
  344. m_currentProgramName = _m.getQString();
  345. break;
  346. case IdVstProgramNames:
  347. m_allProgramNames = _m.getQString();
  348. break;
  349. case IdVstParameterLabels:
  350. m_allParameterLabels = _m.getQString();
  351. break;
  352. case IdVstParameterDisplays:
  353. m_allParameterDisplays = _m.getQString();
  354. break;
  355. case IdVstPluginUniqueID:
  356. // TODO: display graphically in case of failure
  357. printf("unique ID: %s\n", _m.getString().c_str() );
  358. break;
  359. case IdVstParameterDump:
  360. {
  361. m_parameterDump.clear();
  362. const int num_params = _m.getInt();
  363. int p = 0;
  364. for( int i = 0; i < num_params; ++i )
  365. {
  366. VstParameterDumpItem item;
  367. item.index = _m.getInt( ++p );
  368. item.shortLabel = _m.getString( ++p );
  369. item.value = _m.getFloat( ++p );
  370. m_parameterDump["param" + QString::number( item.index )] =
  371. QString::number( item.index ) + ":" +
  372. /*uncomented*/ /*QString( item.shortLabel )*/ QString::fromStdString(item.shortLabel) + ":" +
  373. QString::number( item.value );
  374. }
  375. break;
  376. }
  377. default:
  378. return RemotePlugin::processMessage( _m );
  379. }
  380. return true;
  381. }
  382. QWidget *VstPlugin::editor()
  383. {
  384. return m_pluginWidget;
  385. }
  386. void VstPlugin::openPreset( )
  387. {
  388. FileDialog ofd( NULL, tr( "Open Preset" ), "",
  389. tr( "Vst Plugin Preset (*.fxp *.fxb)" ) );
  390. ofd.setFileMode( FileDialog::ExistingFiles );
  391. if( ofd.exec () == QDialog::Accepted &&
  392. !ofd.selectedFiles().isEmpty() )
  393. {
  394. lock();
  395. sendMessage( message( IdLoadPresetFile ).
  396. addString(
  397. QSTR_TO_STDSTR(
  398. QDir::toNativeSeparators( ofd.selectedFiles()[0] ) ) )
  399. );
  400. waitForMessage( IdLoadPresetFile, true );
  401. unlock();
  402. }
  403. }
  404. void VstPlugin::setProgram( int index )
  405. {
  406. lock();
  407. sendMessage( message( IdVstSetProgram ).addInt( index ) );
  408. waitForMessage( IdVstSetProgram, true );
  409. unlock();
  410. }
  411. void VstPlugin::rotateProgram( int offset )
  412. {
  413. lock();
  414. sendMessage( message( IdVstRotateProgram ).addInt( offset ) );
  415. waitForMessage( IdVstRotateProgram, true );
  416. unlock();
  417. }
  418. void VstPlugin::loadProgramNames()
  419. {
  420. lock();
  421. sendMessage( message( IdVstProgramNames ) );
  422. waitForMessage( IdVstProgramNames, true );
  423. unlock();
  424. }
  425. void VstPlugin::loadParameterLabels()
  426. {
  427. lock();
  428. sendMessage( message( IdVstParameterLabels ) );
  429. waitForMessage( IdVstParameterLabels, true );
  430. unlock();
  431. }
  432. void VstPlugin::loadParameterDisplays()
  433. {
  434. lock();
  435. sendMessage( message( IdVstParameterDisplays ) );
  436. waitForMessage( IdVstParameterDisplays, true );
  437. unlock();
  438. }
  439. void VstPlugin::savePreset( )
  440. {
  441. QString presName = currentProgramName().isEmpty() ? tr(": default") : currentProgramName();
  442. presName.replace("\"", "'"); // QFileDialog unable to handle double quotes properly
  443. FileDialog sfd( NULL, tr( "Save Preset" ), presName.section(": ", 1, 1) + tr(".fxp"),
  444. tr( "Vst Plugin Preset (*.fxp *.fxb)" ) );
  445. if( p_name != "" ) // remember last directory
  446. {
  447. sfd.setDirectory( QFileInfo( p_name ).absolutePath() );
  448. }
  449. sfd.setAcceptMode( FileDialog::AcceptSave );
  450. sfd.setFileMode( FileDialog::AnyFile );
  451. if( sfd.exec () == QDialog::Accepted &&
  452. !sfd.selectedFiles().isEmpty() && sfd.selectedFiles()[0] != "" )
  453. {
  454. QString fns = sfd.selectedFiles()[0];
  455. p_name = fns;
  456. if ((fns.toUpper().indexOf(tr(".FXP")) == -1) && (fns.toUpper().indexOf(tr(".FXB")) == -1))
  457. fns = fns + tr(".fxb");
  458. else fns = fns.left(fns.length() - 4) + (fns.right( 4 )).toLower();
  459. lock();
  460. sendMessage( message( IdSavePresetFile ).
  461. addString(
  462. QSTR_TO_STDSTR(
  463. QDir::toNativeSeparators( fns ) ) )
  464. );
  465. waitForMessage( IdSavePresetFile, true );
  466. unlock();
  467. }
  468. }
  469. void VstPlugin::setParam( int i, float f )
  470. {
  471. lock();
  472. sendMessage( message( IdVstSetParameter ).addInt( i ).addFloat( f ) );
  473. //waitForMessage( IdVstSetParameter, true );
  474. unlock();
  475. }
  476. void VstPlugin::idleUpdate()
  477. {
  478. lock();
  479. sendMessage( message( IdVstIdleUpdate ) );
  480. unlock();
  481. }
  482. void VstPlugin::showUI()
  483. {
  484. if ( m_embedMethod == "none" )
  485. {
  486. RemotePlugin::showUI();
  487. }
  488. else if ( m_embedMethod != "headless" )
  489. {
  490. if (! editor()) {
  491. qWarning() << "VstPlugin::showUI called before VstPlugin::createUI";
  492. }
  493. toggleEditorVisibility( true );
  494. }
  495. }
  496. void VstPlugin::hideUI()
  497. {
  498. if ( m_embedMethod == "none" )
  499. {
  500. RemotePlugin::hideUI();
  501. }
  502. else if ( pluginWidget() != nullptr )
  503. {
  504. toggleEditorVisibility( false );
  505. }
  506. }
  507. // X11Embed only
  508. void VstPlugin::handleClientEmbed()
  509. {
  510. lock();
  511. sendMessage( IdShowUI );
  512. unlock();
  513. }
  514. void VstPlugin::loadChunk( const QByteArray & _chunk )
  515. {
  516. QTemporaryFile tf;
  517. if( tf.open() )
  518. {
  519. tf.write( _chunk );
  520. tf.flush();
  521. lock();
  522. sendMessage( message( IdLoadSettingsFromFile ).
  523. addString(
  524. QSTR_TO_STDSTR(
  525. QDir::toNativeSeparators( tf.fileName() ) ) ).
  526. addInt( _chunk.size() ) );
  527. waitForMessage( IdLoadSettingsFromFile, true );
  528. unlock();
  529. }
  530. }
  531. QByteArray VstPlugin::saveChunk()
  532. {
  533. QByteArray a;
  534. QTemporaryFile tf;
  535. if( tf.open() )
  536. {
  537. lock();
  538. sendMessage( message( IdSaveSettingsToFile ).
  539. addString(
  540. QSTR_TO_STDSTR(
  541. QDir::toNativeSeparators( tf.fileName() ) ) ) );
  542. waitForMessage( IdSaveSettingsToFile, true );
  543. unlock();
  544. a = tf.readAll();
  545. }
  546. return a;
  547. }
  548. void VstPlugin::toggleEditorVisibility( int visible )
  549. {
  550. QWidget* w = editor();
  551. if ( ! w ) {
  552. return;
  553. }
  554. if ( visible < 0 ) {
  555. visible = ! w->isVisible();
  556. }
  557. w->setVisible( visible );
  558. }
  559. void VstPlugin::createUI( QWidget * parent )
  560. {
  561. if ( m_pluginWidget ) {
  562. qWarning() << "VstPlugin::createUI called twice";
  563. m_pluginWidget->setParent( parent );
  564. return;
  565. }
  566. if( m_pluginWindowID == 0 )
  567. {
  568. return;
  569. }
  570. QWidget* container = nullptr;
  571. #if QT_VERSION >= 0x050100
  572. if (m_embedMethod == "qt" )
  573. {
  574. QWindow* vw = QWindow::fromWinId(m_pluginWindowID);
  575. container = QWidget::createWindowContainer(vw, parent );
  576. container->installEventFilter(this);
  577. } else
  578. #endif
  579. #ifdef LMMS_BUILD_WIN32
  580. if (m_embedMethod == "win32" )
  581. {
  582. QWidget * helper = new QWidget;
  583. QHBoxLayout * l = new QHBoxLayout( helper );
  584. QWidget * target = new QWidget( helper );
  585. l->setSpacing( 0 );
  586. l->setMargin( 0 );
  587. l->addWidget( target );
  588. // we've to call that for making sure, Qt created the windows
  589. helper->winId();
  590. HWND targetHandle = (HWND)target->winId();
  591. HWND pluginHandle = (HWND)(intptr_t)m_pluginWindowID;
  592. DWORD style = GetWindowLong(pluginHandle, GWL_STYLE);
  593. style = style & ~(WS_POPUP);
  594. style = style | WS_CHILD;
  595. SetWindowLong(pluginHandle, GWL_STYLE, style);
  596. SetParent(pluginHandle, targetHandle);
  597. DWORD threadId = GetWindowThreadProcessId(pluginHandle, NULL);
  598. DWORD currentThreadId = GetCurrentThreadId();
  599. AttachThreadInput(currentThreadId, threadId, true);
  600. container = helper;
  601. RemotePlugin::showUI();
  602. } else
  603. #endif
  604. #ifdef LMMS_BUILD_LINUX
  605. if (m_embedMethod == "xembed" )
  606. {
  607. if (parent)
  608. {
  609. parent->setAttribute(Qt::WA_NativeWindow);
  610. }
  611. QX11EmbedContainer * embedContainer = new QX11EmbedContainer( parent );
  612. connect(embedContainer, SIGNAL(clientIsEmbedded()), this, SLOT(handleClientEmbed()));
  613. embedContainer->embedClient( m_pluginWindowID );
  614. container = embedContainer;
  615. } else
  616. #endif
  617. {
  618. qCritical() << "Unknown embed method" << m_embedMethod;
  619. return;
  620. }
  621. container->setFixedSize( m_pluginGeometry );
  622. container->setWindowTitle( name() );
  623. m_pluginWidget = container;
  624. }
  625. bool VstPlugin::eventFilter(QObject *obj, QEvent *event)
  626. {
  627. #if QT_VERSION >= 0x050100
  628. if (embedMethod() == "qt" && obj == m_pluginWidget)
  629. {
  630. if (event->type() == QEvent::Show) {
  631. RemotePlugin::showUI();
  632. }
  633. qDebug() << obj << event;
  634. }
  635. #endif
  636. return false;
  637. }
  638. QString VstPlugin::embedMethod() const
  639. {
  640. return m_embedMethod;
  641. }