RemotePlugin.h 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458
  1. /*
  2. * RemotePlugin.h - base class providing RPC like mechanisms
  3. *
  4. * Copyright (c) 2008-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. #ifndef REMOTE_PLUGIN_H
  25. #define REMOTE_PLUGIN_H
  26. #include "MidiEvent.h"
  27. #include "VstSyncData.h"
  28. #include <atomic>
  29. #include <vector>
  30. #include <cstdio>
  31. #include <cstdlib>
  32. #include <cstring>
  33. #include <string>
  34. #include <cassert>
  35. #if !(defined(LMMS_HAVE_SYS_IPC_H) && defined(LMMS_HAVE_SEMAPHORE_H))
  36. #define SYNC_WITH_SHM_FIFO
  37. #define USE_QT_SEMAPHORES
  38. #ifdef LMMS_HAVE_PROCESS_H
  39. #include <process.h>
  40. #endif
  41. #include <QtCore/QtGlobal>
  42. #include <QtCore/QSystemSemaphore>
  43. #endif
  44. #ifdef LMMS_HAVE_SYS_SHM_H
  45. #include <sys/shm.h>
  46. #ifdef LMMS_HAVE_UNISTD_H
  47. #include <unistd.h>
  48. #endif
  49. #else
  50. #define USE_QT_SHMEM
  51. #include <QtCore/QtGlobal>
  52. #include <QtCore/QSharedMemory>
  53. #if !defined(LMMS_HAVE_SYS_TYPES_H) || defined(LMMS_BUILD_WIN32)
  54. typedef int32_t key_t;
  55. #endif
  56. #endif
  57. #ifdef LMMS_HAVE_LOCALE_H
  58. #include <locale.h>
  59. #endif
  60. #ifdef LMMS_HAVE_PTHREAD_H
  61. #include <pthread.h>
  62. #endif
  63. #ifdef BUILD_REMOTE_PLUGIN_CLIENT
  64. #undef LMMS_EXPORT
  65. #define LMMS_EXPORT
  66. #define COMPILE_REMOTE_PLUGIN_BASE
  67. #ifndef SYNC_WITH_SHM_FIFO
  68. #include <sys/socket.h>
  69. #include <sys/un.h>
  70. #endif
  71. #else
  72. #include "lmms_export.h"
  73. #include <QtCore/QMutex>
  74. #include <QtCore/QProcess>
  75. #include <QtCore/QThread>
  76. #include <QtCore/QString>
  77. #ifndef SYNC_WITH_SHM_FIFO
  78. #include <poll.h>
  79. #include <unistd.h>
  80. #endif
  81. #endif
  82. #ifdef SYNC_WITH_SHM_FIFO
  83. // sometimes we need to exchange bigger messages (e.g. for VST parameter dumps)
  84. // so set a usable value here
  85. const int SHM_FIFO_SIZE = 512*1024;
  86. // implements a FIFO inside a shared memory segment
  87. class shmFifo
  88. {
  89. // need this union to handle different sizes of sem_t on 32 bit
  90. // and 64 bit platforms
  91. union sem32_t
  92. {
  93. int semKey;
  94. char fill[32];
  95. } ;
  96. struct shmData
  97. {
  98. sem32_t dataSem; // semaphore for locking this
  99. // FIFO management data
  100. sem32_t messageSem; // semaphore for incoming messages
  101. volatile int32_t startPtr; // current start of FIFO in memory
  102. volatile int32_t endPtr; // current end of FIFO in memory
  103. char data[SHM_FIFO_SIZE]; // actual data
  104. } ;
  105. public:
  106. // constructor for master-side
  107. shmFifo() :
  108. m_invalid( false ),
  109. m_master( true ),
  110. m_shmKey( 0 ),
  111. #ifdef USE_QT_SHMEM
  112. m_shmObj(),
  113. #else
  114. m_shmID( -1 ),
  115. #endif
  116. m_data( nullptr ),
  117. m_dataSem( QString() ),
  118. m_messageSem( QString() ),
  119. m_lockDepth( 0 )
  120. {
  121. #ifdef USE_QT_SHMEM
  122. do
  123. {
  124. m_shmObj.setKey( QString( "%1" ).arg( ++m_shmKey ) );
  125. m_shmObj.create( sizeof( shmData ) );
  126. } while( m_shmObj.error() != QSharedMemory::NoError );
  127. m_data = (shmData *) m_shmObj.data();
  128. #else
  129. while( ( m_shmID = shmget( ++m_shmKey, sizeof( shmData ),
  130. IPC_CREAT | IPC_EXCL | 0600 ) ) == -1 )
  131. {
  132. }
  133. m_data = (shmData *) shmat( m_shmID, 0, 0 );
  134. #endif
  135. assert( m_data != nullptr );
  136. m_data->startPtr = m_data->endPtr = 0;
  137. static int k = 0;
  138. m_data->dataSem.semKey = ( getpid()<<10 ) + ++k;
  139. m_data->messageSem.semKey = ( getpid()<<10 ) + ++k;
  140. m_dataSem.setKey( QString::number( m_data->dataSem.semKey ),
  141. 1, QSystemSemaphore::Create );
  142. m_messageSem.setKey( QString::number(
  143. m_data->messageSem.semKey ),
  144. 0, QSystemSemaphore::Create );
  145. }
  146. // constructor for remote-/client-side - use _shm_key for making up
  147. // the connection to master
  148. shmFifo( key_t _shm_key ) :
  149. m_invalid( false ),
  150. m_master( false ),
  151. m_shmKey( 0 ),
  152. #ifdef USE_QT_SHMEM
  153. m_shmObj( QString::number( _shm_key ) ),
  154. #else
  155. m_shmID( shmget( _shm_key, 0, 0 ) ),
  156. #endif
  157. m_data( nullptr ),
  158. m_dataSem( QString() ),
  159. m_messageSem( QString() ),
  160. m_lockDepth( 0 )
  161. {
  162. #ifdef USE_QT_SHMEM
  163. if( m_shmObj.attach() )
  164. {
  165. m_data = (shmData *) m_shmObj.data();
  166. }
  167. #else
  168. if( m_shmID != -1 )
  169. {
  170. m_data = (shmData *) shmat( m_shmID, 0, 0 );
  171. }
  172. #endif
  173. assert( m_data != nullptr );
  174. m_dataSem.setKey( QString::number( m_data->dataSem.semKey ) );
  175. m_messageSem.setKey( QString::number(
  176. m_data->messageSem.semKey ) );
  177. }
  178. ~shmFifo()
  179. {
  180. // master?
  181. if( m_master )
  182. {
  183. #ifndef USE_QT_SHMEM
  184. shmctl( m_shmID, IPC_RMID, nullptr );
  185. #endif
  186. }
  187. #ifndef USE_QT_SHMEM
  188. shmdt( m_data );
  189. #endif
  190. }
  191. inline bool isInvalid() const
  192. {
  193. return m_invalid;
  194. }
  195. void invalidate()
  196. {
  197. m_invalid = true;
  198. }
  199. // do we act as master (i.e. not as remote-process?)
  200. inline bool isMaster() const
  201. {
  202. return m_master;
  203. }
  204. // recursive lock
  205. inline void lock()
  206. {
  207. if( !isInvalid() && m_lockDepth.fetch_add( 1 ) == 0 )
  208. {
  209. m_dataSem.acquire();
  210. }
  211. }
  212. // recursive unlock
  213. inline void unlock()
  214. {
  215. if( m_lockDepth.fetch_sub( 1 ) <= 1 )
  216. {
  217. m_dataSem.release();
  218. }
  219. }
  220. // wait until message-semaphore is available
  221. inline void waitForMessage()
  222. {
  223. if( !isInvalid() )
  224. {
  225. m_messageSem.acquire();
  226. }
  227. }
  228. // increase message-semaphore
  229. inline void messageSent()
  230. {
  231. m_messageSem.release();
  232. }
  233. inline int32_t readInt()
  234. {
  235. int32_t i;
  236. read( &i, sizeof( i ) );
  237. return i;
  238. }
  239. inline void writeInt( const int32_t & _i )
  240. {
  241. write( &_i, sizeof( _i ) );
  242. }
  243. inline std::string readString()
  244. {
  245. const int len = readInt();
  246. if( len )
  247. {
  248. char * sc = new char[len + 1];
  249. read( sc, len );
  250. sc[len] = 0;
  251. std::string s( sc );
  252. delete[] sc;
  253. return s;
  254. }
  255. return std::string();
  256. }
  257. inline void writeString( const std::string & _s )
  258. {
  259. const int len = _s.size();
  260. writeInt( len );
  261. write( _s.c_str(), len );
  262. }
  263. inline bool messagesLeft()
  264. {
  265. if( isInvalid() )
  266. {
  267. return false;
  268. }
  269. lock();
  270. const bool empty = ( m_data->startPtr == m_data->endPtr );
  271. unlock();
  272. return !empty;
  273. }
  274. inline int shmKey() const
  275. {
  276. return m_shmKey;
  277. }
  278. private:
  279. static inline void fastMemCpy( void * _dest, const void * _src,
  280. const int _len )
  281. {
  282. // calling memcpy() for just an integer is obsolete overhead
  283. if( _len == 4 )
  284. {
  285. *( (int32_t *) _dest ) = *( (int32_t *) _src );
  286. }
  287. else
  288. {
  289. memcpy( _dest, _src, _len );
  290. }
  291. }
  292. void read( void * _buf, int _len )
  293. {
  294. if( isInvalid() )
  295. {
  296. memset( _buf, 0, _len );
  297. return;
  298. }
  299. lock();
  300. while( isInvalid() == false &&
  301. _len > m_data->endPtr - m_data->startPtr )
  302. {
  303. unlock();
  304. #ifndef LMMS_BUILD_WIN32
  305. usleep( 5 );
  306. #endif
  307. lock();
  308. }
  309. fastMemCpy( _buf, m_data->data + m_data->startPtr, _len );
  310. m_data->startPtr += _len;
  311. // nothing left?
  312. if( m_data->startPtr == m_data->endPtr )
  313. {
  314. // then reset to 0
  315. m_data->startPtr = m_data->endPtr = 0;
  316. }
  317. unlock();
  318. }
  319. void write( const void * _buf, int _len )
  320. {
  321. if( isInvalid() || _len > SHM_FIFO_SIZE )
  322. {
  323. return;
  324. }
  325. lock();
  326. while( _len > SHM_FIFO_SIZE - m_data->endPtr )
  327. {
  328. // if no space is left, try to move data to front
  329. if( m_data->startPtr > 0 )
  330. {
  331. memmove( m_data->data,
  332. m_data->data + m_data->startPtr,
  333. m_data->endPtr - m_data->startPtr );
  334. m_data->endPtr = m_data->endPtr -
  335. m_data->startPtr;
  336. m_data->startPtr = 0;
  337. }
  338. unlock();
  339. #ifndef LMMS_BUILD_WIN32
  340. usleep( 5 );
  341. #endif
  342. lock();
  343. }
  344. fastMemCpy( m_data->data + m_data->endPtr, _buf, _len );
  345. m_data->endPtr += _len;
  346. unlock();
  347. }
  348. volatile bool m_invalid;
  349. bool m_master;
  350. key_t m_shmKey;
  351. #ifdef USE_QT_SHMEM
  352. QSharedMemory m_shmObj;
  353. #else
  354. int m_shmID;
  355. #endif
  356. shmData * m_data;
  357. QSystemSemaphore m_dataSem;
  358. QSystemSemaphore m_messageSem;
  359. std::atomic_int m_lockDepth;
  360. } ;
  361. #endif
  362. enum RemoteMessageIDs
  363. {
  364. IdUndefined,
  365. IdHostInfoGotten,
  366. IdInitDone,
  367. IdQuit,
  368. IdSampleRateInformation,
  369. IdBufferSizeInformation,
  370. IdInformationUpdated,
  371. IdMidiEvent,
  372. IdStartProcessing,
  373. IdProcessingDone,
  374. IdChangeSharedMemoryKey,
  375. IdChangeInputCount,
  376. IdChangeOutputCount,
  377. IdChangeInputOutputCount,
  378. IdShowUI,
  379. IdHideUI,
  380. IdToggleUI,
  381. IdIsUIVisible,
  382. IdSaveSettingsToString,
  383. IdSaveSettingsToFile,
  384. IdLoadSettingsFromString,
  385. IdLoadSettingsFromFile,
  386. IdSavePresetFile,
  387. IdLoadPresetFile,
  388. IdDebugMessage,
  389. IdUserBase = 64
  390. } ;
  391. class LMMS_EXPORT RemotePluginBase
  392. {
  393. public:
  394. struct message
  395. {
  396. message() :
  397. id( IdUndefined ),
  398. data()
  399. {
  400. }
  401. message( const message & _m ) :
  402. id( _m.id ),
  403. data( _m.data )
  404. {
  405. }
  406. message( int _id ) :
  407. id( _id ),
  408. data()
  409. {
  410. }
  411. inline message & addString( const std::string & _s )
  412. {
  413. data.push_back( _s );
  414. return *this;
  415. }
  416. message & addInt( int _i )
  417. {
  418. char buf[32];
  419. sprintf( buf, "%d", _i );
  420. data.push_back( std::string( buf ) );
  421. return *this;
  422. }
  423. message & addFloat( float _f )
  424. {
  425. char buf[32];
  426. sprintf( buf, "%f", _f );
  427. data.push_back( std::string( buf ) );
  428. return *this;
  429. }
  430. inline std::string getString( int _p = 0 ) const
  431. {
  432. return data[_p];
  433. }
  434. #ifndef BUILD_REMOTE_PLUGIN_CLIENT
  435. inline QString getQString( int _p = 0 ) const
  436. {
  437. return QString::fromStdString( getString( _p ) );
  438. }
  439. #endif
  440. inline int getInt( int _p = 0 ) const
  441. {
  442. return atoi( data[_p].c_str() );
  443. }
  444. inline float getFloat( int _p ) const
  445. {
  446. return (float) atof( data[_p].c_str() );
  447. }
  448. inline bool operator==( const message & _m ) const
  449. {
  450. return( id == _m.id );
  451. }
  452. int id;
  453. private:
  454. std::vector<std::string> data;
  455. friend class RemotePluginBase;
  456. } ;
  457. #ifdef SYNC_WITH_SHM_FIFO
  458. RemotePluginBase( shmFifo * _in, shmFifo * _out );
  459. #else
  460. RemotePluginBase();
  461. #endif
  462. virtual ~RemotePluginBase();
  463. #ifdef SYNC_WITH_SHM_FIFO
  464. void reset( shmFifo *in, shmFifo *out )
  465. {
  466. delete m_in;
  467. delete m_out;
  468. m_in = in;
  469. m_out = out;
  470. }
  471. #endif
  472. int sendMessage( const message & _m );
  473. message receiveMessage();
  474. inline bool isInvalid() const
  475. {
  476. #ifdef SYNC_WITH_SHM_FIFO
  477. return m_in->isInvalid() || m_out->isInvalid();
  478. #else
  479. return m_invalid;
  480. #endif
  481. }
  482. message waitForMessage( const message & _m,
  483. bool _busy_waiting = false );
  484. inline message fetchAndProcessNextMessage()
  485. {
  486. message m = receiveMessage();
  487. processMessage( m );
  488. return m;
  489. }
  490. #ifndef SYNC_WITH_SHM_FIFO
  491. inline int32_t readInt()
  492. {
  493. int32_t i;
  494. read( &i, sizeof( i ) );
  495. return i;
  496. }
  497. inline void writeInt( const int32_t & _i )
  498. {
  499. write( &_i, sizeof( _i ) );
  500. }
  501. inline std::string readString()
  502. {
  503. const int len = readInt();
  504. if( len )
  505. {
  506. char * sc = new char[len + 1];
  507. read( sc, len );
  508. sc[len] = 0;
  509. std::string s( sc );
  510. delete[] sc;
  511. return s;
  512. }
  513. return std::string();
  514. }
  515. inline void writeString( const std::string & _s )
  516. {
  517. const int len = _s.size();
  518. writeInt( len );
  519. write( _s.c_str(), len );
  520. }
  521. #endif
  522. #ifndef BUILD_REMOTE_PLUGIN_CLIENT
  523. inline bool messagesLeft()
  524. {
  525. #ifdef SYNC_WITH_SHM_FIFO
  526. return m_in->messagesLeft();
  527. #else
  528. struct pollfd pollin;
  529. pollin.fd = m_socket;
  530. pollin.events = POLLIN;
  531. if ( poll( &pollin, 1, 0 ) == -1 )
  532. {
  533. qWarning( "Unexpected poll error." );
  534. }
  535. return pollin.revents & POLLIN;
  536. #endif
  537. }
  538. inline void fetchAndProcessAllMessages()
  539. {
  540. while( messagesLeft() )
  541. {
  542. fetchAndProcessNextMessage();
  543. }
  544. }
  545. static bool isMainThreadWaiting()
  546. {
  547. return waitDepthCounter() > 0;
  548. }
  549. #endif
  550. virtual bool processMessage( const message & _m ) = 0;
  551. protected:
  552. #ifdef SYNC_WITH_SHM_FIFO
  553. inline const shmFifo * in() const
  554. {
  555. return m_in;
  556. }
  557. inline const shmFifo * out() const
  558. {
  559. return m_out;
  560. }
  561. #endif
  562. inline void invalidate()
  563. {
  564. #ifdef SYNC_WITH_SHM_FIFO
  565. m_in->invalidate();
  566. m_out->invalidate();
  567. m_in->messageSent();
  568. #else
  569. m_invalid = true;
  570. #endif
  571. }
  572. #ifndef SYNC_WITH_SHM_FIFO
  573. int m_socket;
  574. #endif
  575. private:
  576. #ifndef BUILD_REMOTE_PLUGIN_CLIENT
  577. static int & waitDepthCounter()
  578. {
  579. static int waitDepth = 0;
  580. return waitDepth;
  581. }
  582. #endif
  583. #ifdef SYNC_WITH_SHM_FIFO
  584. shmFifo * m_in;
  585. shmFifo * m_out;
  586. #else
  587. void read( void * _buf, int _len )
  588. {
  589. if( isInvalid() )
  590. {
  591. memset( _buf, 0, _len );
  592. return;
  593. }
  594. char * buf = (char *) _buf;
  595. int remaining = _len;
  596. while ( remaining )
  597. {
  598. ssize_t nread = ::read( m_socket, buf, remaining );
  599. switch ( nread )
  600. {
  601. case -1:
  602. fprintf( stderr,
  603. "Error while reading.\n" );
  604. case 0:
  605. invalidate();
  606. memset( _buf, 0, _len );
  607. return;
  608. }
  609. buf += nread;
  610. remaining -= nread;
  611. }
  612. }
  613. void write( const void * _buf, int _len )
  614. {
  615. if( isInvalid() )
  616. {
  617. return;
  618. }
  619. const char * buf = (const char *) _buf;
  620. int remaining = _len;
  621. while ( remaining )
  622. {
  623. ssize_t nwritten = ::write( m_socket, buf, remaining );
  624. switch ( nwritten )
  625. {
  626. case -1:
  627. fprintf( stderr,
  628. "Error while writing.\n" );
  629. case 0:
  630. invalidate();
  631. return;
  632. }
  633. buf += nwritten;
  634. remaining -= nwritten;
  635. }
  636. }
  637. bool m_invalid;
  638. pthread_mutex_t m_receiveMutex;
  639. pthread_mutex_t m_sendMutex;
  640. #endif
  641. } ;
  642. #ifndef BUILD_REMOTE_PLUGIN_CLIENT
  643. class RemotePlugin;
  644. class ProcessWatcher : public QThread
  645. {
  646. Q_OBJECT
  647. public:
  648. ProcessWatcher( RemotePlugin * );
  649. virtual ~ProcessWatcher() = default;
  650. void stop()
  651. {
  652. m_quit = true;
  653. quit();
  654. }
  655. void reset()
  656. {
  657. m_quit = false;
  658. }
  659. private:
  660. void run() override;
  661. RemotePlugin * m_plugin;
  662. volatile bool m_quit;
  663. } ;
  664. class LMMS_EXPORT RemotePlugin : public QObject, public RemotePluginBase
  665. {
  666. Q_OBJECT
  667. public:
  668. RemotePlugin();
  669. virtual ~RemotePlugin();
  670. inline bool isRunning()
  671. {
  672. #ifdef DEBUG_REMOTE_PLUGIN
  673. return true;
  674. #else
  675. return m_process.state() != QProcess::NotRunning;
  676. #endif
  677. }
  678. bool init( const QString &pluginExecutable, bool waitForInitDoneMsg, QStringList extraArgs = {} );
  679. inline void waitForHostInfoGotten()
  680. {
  681. m_failed = waitForMessage( IdHostInfoGotten ).id
  682. != IdHostInfoGotten;
  683. }
  684. inline void waitForInitDone( bool _busyWaiting = true )
  685. {
  686. m_failed = waitForMessage( IdInitDone, _busyWaiting ).id != IdInitDone;
  687. }
  688. bool processMessage( const message & _m ) override;
  689. bool process( const sampleFrame * _in_buf, sampleFrame * _out_buf );
  690. void processMidiEvent( const MidiEvent&, const f_cnt_t _offset );
  691. void updateSampleRate( sample_rate_t _sr )
  692. {
  693. lock();
  694. sendMessage( message( IdSampleRateInformation ).addInt( _sr ) );
  695. waitForMessage( IdInformationUpdated, true );
  696. unlock();
  697. }
  698. virtual void toggleUI()
  699. {
  700. lock();
  701. sendMessage( IdToggleUI );
  702. unlock();
  703. }
  704. int isUIVisible()
  705. {
  706. lock();
  707. sendMessage( IdIsUIVisible );
  708. unlock();
  709. message m = waitForMessage( IdIsUIVisible );
  710. return m.id != IdIsUIVisible ? -1 : m.getInt() ? 1 : 0;
  711. }
  712. inline bool failed() const
  713. {
  714. return m_failed;
  715. }
  716. inline void lock()
  717. {
  718. m_commMutex.lock();
  719. }
  720. inline void unlock()
  721. {
  722. m_commMutex.unlock();
  723. }
  724. public slots:
  725. virtual void showUI();
  726. virtual void hideUI();
  727. protected:
  728. inline void setSplittedChannels( bool _on )
  729. {
  730. m_splitChannels = _on;
  731. }
  732. bool m_failed;
  733. private:
  734. void resizeSharedProcessingMemory();
  735. QProcess m_process;
  736. ProcessWatcher m_watcher;
  737. QString m_exec;
  738. QStringList m_args;
  739. QMutex m_commMutex;
  740. bool m_splitChannels;
  741. #ifdef USE_QT_SHMEM
  742. QSharedMemory m_shmObj;
  743. #else
  744. int m_shmID;
  745. #endif
  746. size_t m_shmSize;
  747. float * m_shm;
  748. int m_inputCount;
  749. int m_outputCount;
  750. #ifndef SYNC_WITH_SHM_FIFO
  751. int m_server;
  752. QString m_socketFile;
  753. #endif
  754. friend class ProcessWatcher;
  755. private slots:
  756. void processFinished( int exitCode, QProcess::ExitStatus exitStatus );
  757. void processErrored(QProcess::ProcessError err );
  758. } ;
  759. #endif
  760. #ifdef BUILD_REMOTE_PLUGIN_CLIENT
  761. class RemotePluginClient : public RemotePluginBase
  762. {
  763. public:
  764. #ifdef SYNC_WITH_SHM_FIFO
  765. RemotePluginClient( key_t _shm_in, key_t _shm_out );
  766. #else
  767. RemotePluginClient( const char * socketPath );
  768. #endif
  769. virtual ~RemotePluginClient();
  770. #ifdef USE_QT_SHMEM
  771. VstSyncData * getQtVSTshm();
  772. #endif
  773. virtual bool processMessage( const message & _m );
  774. virtual void process( const sampleFrame * _in_buf,
  775. sampleFrame * _out_buf ) = 0;
  776. virtual void processMidiEvent( const MidiEvent&, const f_cnt_t /* _offset */ )
  777. {
  778. }
  779. inline float * sharedMemory()
  780. {
  781. return m_shm;
  782. }
  783. virtual void updateSampleRate()
  784. {
  785. }
  786. virtual void updateBufferSize()
  787. {
  788. }
  789. inline sample_rate_t sampleRate() const
  790. {
  791. return m_sampleRate;
  792. }
  793. inline fpp_t bufferSize() const
  794. {
  795. return m_bufferSize;
  796. }
  797. void setInputCount( int _i )
  798. {
  799. m_inputCount = _i;
  800. sendMessage( message( IdChangeInputCount ).addInt( _i ) );
  801. }
  802. void setOutputCount( int _i )
  803. {
  804. m_outputCount = _i;
  805. sendMessage( message( IdChangeOutputCount ).addInt( _i ) );
  806. }
  807. void setInputOutputCount( int i, int o )
  808. {
  809. m_inputCount = i;
  810. m_outputCount = o;
  811. sendMessage( message( IdChangeInputOutputCount )
  812. .addInt( i )
  813. .addInt( o ) );
  814. }
  815. virtual int inputCount() const
  816. {
  817. return m_inputCount;
  818. }
  819. virtual int outputCount() const
  820. {
  821. return m_outputCount;
  822. }
  823. void debugMessage( const std::string & _s )
  824. {
  825. sendMessage( message( IdDebugMessage ).addString( _s ) );
  826. }
  827. private:
  828. void setShmKey( key_t _key, int _size );
  829. void doProcessing();
  830. #ifdef USE_QT_SHMEM
  831. QSharedMemory m_shmObj;
  832. QSharedMemory m_shmQtID;
  833. #endif
  834. VstSyncData * m_vstSyncData;
  835. float * m_shm;
  836. int m_inputCount;
  837. int m_outputCount;
  838. sample_rate_t m_sampleRate;
  839. fpp_t m_bufferSize;
  840. } ;
  841. #endif
  842. #ifdef COMPILE_REMOTE_PLUGIN_BASE
  843. #ifndef BUILD_REMOTE_PLUGIN_CLIENT
  844. #include <QtCore/QCoreApplication>
  845. #endif
  846. #ifdef SYNC_WITH_SHM_FIFO
  847. RemotePluginBase::RemotePluginBase( shmFifo * _in, shmFifo * _out ) :
  848. m_in( _in ),
  849. m_out( _out )
  850. #else
  851. RemotePluginBase::RemotePluginBase() :
  852. m_socket( -1 ),
  853. m_invalid( false )
  854. #endif
  855. {
  856. #ifdef LMMS_HAVE_LOCALE_H
  857. // make sure, we're using common ways to print/scan
  858. // floats to/from strings (',' vs. '.' for decimal point etc.)
  859. setlocale( LC_NUMERIC, "C" );
  860. #endif
  861. #ifndef SYNC_WITH_SHM_FIFO
  862. pthread_mutex_init( &m_receiveMutex, nullptr );
  863. pthread_mutex_init( &m_sendMutex, nullptr );
  864. #endif
  865. }
  866. RemotePluginBase::~RemotePluginBase()
  867. {
  868. #ifdef SYNC_WITH_SHM_FIFO
  869. delete m_in;
  870. delete m_out;
  871. #else
  872. pthread_mutex_destroy( &m_receiveMutex );
  873. pthread_mutex_destroy( &m_sendMutex );
  874. #endif
  875. }
  876. int RemotePluginBase::sendMessage( const message & _m )
  877. {
  878. #ifdef SYNC_WITH_SHM_FIFO
  879. m_out->lock();
  880. m_out->writeInt( _m.id );
  881. m_out->writeInt( _m.data.size() );
  882. int j = 8;
  883. for( unsigned int i = 0; i < _m.data.size(); ++i )
  884. {
  885. m_out->writeString( _m.data[i] );
  886. j += 4 + _m.data[i].size();
  887. }
  888. m_out->unlock();
  889. m_out->messageSent();
  890. #else
  891. pthread_mutex_lock( &m_sendMutex );
  892. writeInt( _m.id );
  893. writeInt( _m.data.size() );
  894. int j = 8;
  895. for( unsigned int i = 0; i < _m.data.size(); ++i )
  896. {
  897. writeString( _m.data[i] );
  898. j += 4 + _m.data[i].size();
  899. }
  900. pthread_mutex_unlock( &m_sendMutex );
  901. #endif
  902. return j;
  903. }
  904. RemotePluginBase::message RemotePluginBase::receiveMessage()
  905. {
  906. #ifdef SYNC_WITH_SHM_FIFO
  907. m_in->waitForMessage();
  908. m_in->lock();
  909. message m;
  910. m.id = m_in->readInt();
  911. const int s = m_in->readInt();
  912. for( int i = 0; i < s; ++i )
  913. {
  914. m.data.push_back( m_in->readString() );
  915. }
  916. m_in->unlock();
  917. #else
  918. pthread_mutex_lock( &m_receiveMutex );
  919. message m;
  920. m.id = readInt();
  921. const int s = readInt();
  922. for( int i = 0; i < s; ++i )
  923. {
  924. m.data.push_back( readString() );
  925. }
  926. pthread_mutex_unlock( &m_receiveMutex );
  927. #endif
  928. return m;
  929. }
  930. RemotePluginBase::message RemotePluginBase::waitForMessage(
  931. const message & _wm,
  932. bool _busy_waiting )
  933. {
  934. #ifndef BUILD_REMOTE_PLUGIN_CLIENT
  935. if( _busy_waiting )
  936. {
  937. // No point processing events outside of the main thread
  938. _busy_waiting = QThread::currentThread() ==
  939. QCoreApplication::instance()->thread();
  940. }
  941. struct WaitDepthCounter
  942. {
  943. WaitDepthCounter( int & depth, bool busy ) :
  944. m_depth( depth ),
  945. m_busy( busy )
  946. {
  947. if( m_busy ) { ++m_depth; }
  948. }
  949. ~WaitDepthCounter()
  950. {
  951. if( m_busy ) { --m_depth; }
  952. }
  953. int & m_depth;
  954. bool m_busy;
  955. };
  956. WaitDepthCounter wdc( waitDepthCounter(), _busy_waiting );
  957. #endif
  958. while( !isInvalid() )
  959. {
  960. #ifndef BUILD_REMOTE_PLUGIN_CLIENT
  961. if( _busy_waiting && !messagesLeft() )
  962. {
  963. QCoreApplication::processEvents(
  964. QEventLoop::ExcludeUserInputEvents, 50 );
  965. continue;
  966. }
  967. #endif
  968. message m = receiveMessage();
  969. processMessage( m );
  970. if( m.id == _wm.id )
  971. {
  972. return m;
  973. }
  974. else if( m.id == IdUndefined )
  975. {
  976. return m;
  977. }
  978. }
  979. return message();
  980. }
  981. #endif
  982. #ifdef BUILD_REMOTE_PLUGIN_CLIENT
  983. #ifdef SYNC_WITH_SHM_FIFO
  984. RemotePluginClient::RemotePluginClient( key_t _shm_in, key_t _shm_out ) :
  985. RemotePluginBase( new shmFifo( _shm_in ), new shmFifo( _shm_out ) ),
  986. #else
  987. RemotePluginClient::RemotePluginClient( const char * socketPath ) :
  988. RemotePluginBase(),
  989. #endif
  990. #ifdef USE_QT_SHMEM
  991. m_shmObj(),
  992. m_shmQtID( "/usr/bin/lmms" ),
  993. #endif
  994. m_vstSyncData( nullptr ),
  995. m_shm( nullptr ),
  996. m_inputCount( 0 ),
  997. m_outputCount( 0 ),
  998. m_sampleRate( 44100 ),
  999. m_bufferSize( 0 )
  1000. {
  1001. #ifndef SYNC_WITH_SHM_FIFO
  1002. struct sockaddr_un sa;
  1003. sa.sun_family = AF_LOCAL;
  1004. size_t length = strlen( socketPath );
  1005. if ( length >= sizeof sa.sun_path )
  1006. {
  1007. length = sizeof sa.sun_path - 1;
  1008. fprintf( stderr, "Socket path too long.\n" );
  1009. }
  1010. memcpy( sa.sun_path, socketPath, length );
  1011. sa.sun_path[length] = '\0';
  1012. m_socket = socket( PF_LOCAL, SOCK_STREAM, 0 );
  1013. if ( m_socket == -1 )
  1014. {
  1015. fprintf( stderr, "Could not connect to local server.\n" );
  1016. }
  1017. if ( ::connect( m_socket, (struct sockaddr *) &sa, sizeof sa ) == -1 )
  1018. {
  1019. fprintf( stderr, "Could not connect to local server.\n" );
  1020. }
  1021. #endif
  1022. #ifdef USE_QT_SHMEM
  1023. if( m_shmQtID.attach( QSharedMemory::ReadOnly ) )
  1024. {
  1025. m_vstSyncData = (VstSyncData *) m_shmQtID.data();
  1026. m_bufferSize = m_vstSyncData->m_bufferSize;
  1027. m_sampleRate = m_vstSyncData->m_sampleRate;
  1028. sendMessage( IdHostInfoGotten );
  1029. return;
  1030. }
  1031. #else
  1032. key_t key;
  1033. int m_shmID;
  1034. if( ( key = ftok( VST_SNC_SHM_KEY_FILE, 'R' ) ) == -1 )
  1035. {
  1036. perror( "RemotePluginClient::ftok" );
  1037. }
  1038. else
  1039. { // connect to shared memory segment
  1040. if( ( m_shmID = shmget( key, 0, 0 ) ) == -1 )
  1041. {
  1042. perror( "RemotePluginClient::shmget" );
  1043. }
  1044. else
  1045. { // attach segment
  1046. m_vstSyncData = (VstSyncData *)shmat(m_shmID, 0, 0);
  1047. if( m_vstSyncData == (VstSyncData *)( -1 ) )
  1048. {
  1049. perror( "RemotePluginClient::shmat" );
  1050. }
  1051. else
  1052. {
  1053. m_bufferSize = m_vstSyncData->m_bufferSize;
  1054. m_sampleRate = m_vstSyncData->m_sampleRate;
  1055. sendMessage( IdHostInfoGotten );
  1056. // detach segment
  1057. if( shmdt(m_vstSyncData) == -1 )
  1058. {
  1059. perror("RemotePluginClient::shmdt");
  1060. }
  1061. return;
  1062. }
  1063. }
  1064. }
  1065. #endif
  1066. // if attaching shared memory fails
  1067. sendMessage( IdSampleRateInformation );
  1068. sendMessage( IdBufferSizeInformation );
  1069. if( waitForMessage( IdBufferSizeInformation ).id
  1070. != IdBufferSizeInformation )
  1071. {
  1072. fprintf( stderr, "Could not get buffer size information\n" );
  1073. }
  1074. sendMessage( IdHostInfoGotten );
  1075. }
  1076. RemotePluginClient::~RemotePluginClient()
  1077. {
  1078. #ifdef USE_QT_SHMEM
  1079. m_shmQtID.detach();
  1080. #endif
  1081. sendMessage( IdQuit );
  1082. #ifndef USE_QT_SHMEM
  1083. shmdt( m_shm );
  1084. #endif
  1085. #ifndef SYNC_WITH_SHM_FIFO
  1086. if ( close( m_socket ) == -1)
  1087. {
  1088. fprintf( stderr, "Error freeing resources.\n" );
  1089. }
  1090. #endif
  1091. }
  1092. #ifdef USE_QT_SHMEM
  1093. VstSyncData * RemotePluginClient::getQtVSTshm()
  1094. {
  1095. return m_vstSyncData;
  1096. }
  1097. #endif
  1098. bool RemotePluginClient::processMessage( const message & _m )
  1099. {
  1100. message reply_message( _m.id );
  1101. bool reply = false;
  1102. switch( _m.id )
  1103. {
  1104. case IdUndefined:
  1105. return false;
  1106. case IdSampleRateInformation:
  1107. m_sampleRate = _m.getInt();
  1108. updateSampleRate();
  1109. reply_message.id = IdInformationUpdated;
  1110. reply = true;
  1111. break;
  1112. case IdBufferSizeInformation:
  1113. // Should LMMS gain the ability to change buffer size
  1114. // without a restart, it must wait for this message to
  1115. // complete processing or else risk VST crashes
  1116. m_bufferSize = _m.getInt();
  1117. updateBufferSize();
  1118. break;
  1119. case IdQuit:
  1120. return false;
  1121. case IdMidiEvent:
  1122. processMidiEvent(
  1123. MidiEvent( static_cast<MidiEventTypes>(
  1124. _m.getInt( 0 ) ),
  1125. _m.getInt( 1 ),
  1126. _m.getInt( 2 ),
  1127. _m.getInt( 3 ) ),
  1128. _m.getInt( 4 ) );
  1129. break;
  1130. case IdStartProcessing:
  1131. doProcessing();
  1132. reply_message.id = IdProcessingDone;
  1133. reply = true;
  1134. break;
  1135. case IdChangeSharedMemoryKey:
  1136. setShmKey( _m.getInt( 0 ), _m.getInt( 1 ) );
  1137. break;
  1138. case IdInitDone:
  1139. break;
  1140. default:
  1141. {
  1142. char buf[64];
  1143. sprintf( buf, "undefined message: %d\n", (int) _m.id );
  1144. debugMessage( buf );
  1145. break;
  1146. }
  1147. }
  1148. if( reply )
  1149. {
  1150. sendMessage( reply_message );
  1151. }
  1152. return true;
  1153. }
  1154. void RemotePluginClient::setShmKey( key_t _key, int _size )
  1155. {
  1156. #ifdef USE_QT_SHMEM
  1157. m_shmObj.setKey( QString::number( _key ) );
  1158. if( m_shmObj.attach() || m_shmObj.error() == QSharedMemory::NoError )
  1159. {
  1160. m_shm = (float *) m_shmObj.data();
  1161. }
  1162. else
  1163. {
  1164. char buf[64];
  1165. sprintf( buf, "failed getting shared memory: %d\n", m_shmObj.error() );
  1166. debugMessage( buf );
  1167. }
  1168. #else
  1169. if( m_shm != nullptr )
  1170. {
  1171. shmdt( m_shm );
  1172. m_shm = nullptr;
  1173. }
  1174. // only called for detaching SHM?
  1175. if( _key == 0 )
  1176. {
  1177. return;
  1178. }
  1179. int shm_id = shmget( _key, _size, 0 );
  1180. if( shm_id == -1 )
  1181. {
  1182. debugMessage( "failed getting shared memory\n" );
  1183. }
  1184. else
  1185. {
  1186. m_shm = (float *) shmat( shm_id, 0, 0 );
  1187. }
  1188. #endif
  1189. }
  1190. void RemotePluginClient::doProcessing()
  1191. {
  1192. if( m_shm != nullptr )
  1193. {
  1194. process( (sampleFrame *)( m_inputCount > 0 ? m_shm : nullptr ),
  1195. (sampleFrame *)( m_shm +
  1196. ( m_inputCount*m_bufferSize ) ) );
  1197. }
  1198. else
  1199. {
  1200. debugMessage( "doProcessing(): have no shared memory!\n" );
  1201. }
  1202. }
  1203. #else
  1204. LMMS_EXPORT inline std::string QSTR_TO_STDSTR(QString const& qstr)
  1205. {
  1206. return qstr.toStdString();
  1207. }
  1208. #endif
  1209. #endif