RemoteZynAddSubFx.cpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. /*
  2. * RemoteZynAddSubFx.cpp - ZynAddSubFx-embedding plugin
  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. #include <lmmsconfig.h>
  25. #ifdef LMMS_BUILD_WIN32
  26. #include <winsock2.h>
  27. #endif
  28. #include <queue>
  29. #define BUILD_REMOTE_PLUGIN_CLIENT
  30. #include "Note.h"
  31. #include "RemotePlugin.h"
  32. #include "RemoteZynAddSubFx.h"
  33. #include "LocalZynAddSubFx.h"
  34. #include "zynaddsubfx/src/Nio/Nio.h"
  35. #include "zynaddsubfx/src/UI/MasterUI.h"
  36. #include <FL/x.H>
  37. class RemoteZynAddSubFx : public RemotePluginClient, public LocalZynAddSubFx
  38. {
  39. public:
  40. #ifdef SYNC_WITH_SHM_FIFO
  41. RemoteZynAddSubFx( int _shm_in, int _shm_out ) :
  42. RemotePluginClient( _shm_in, _shm_out ),
  43. #else
  44. RemoteZynAddSubFx( const char * socketPath ) :
  45. RemotePluginClient( socketPath ),
  46. #endif
  47. LocalZynAddSubFx(),
  48. m_guiSleepTime( 100 ),
  49. m_guiExit( false )
  50. {
  51. Nio::start();
  52. setInputCount( 0 );
  53. sendMessage( IdInitDone );
  54. waitForMessage( IdInitDone );
  55. pthread_mutex_init( &m_guiMutex, NULL );
  56. pthread_create( &m_messageThreadHandle, NULL, messageLoop, this );
  57. }
  58. virtual ~RemoteZynAddSubFx()
  59. {
  60. Nio::stop();
  61. }
  62. virtual void updateSampleRate()
  63. {
  64. LocalZynAddSubFx::setSampleRate( sampleRate() );
  65. }
  66. virtual void updateBufferSize()
  67. {
  68. LocalZynAddSubFx::setBufferSize( bufferSize() );
  69. }
  70. void messageLoop()
  71. {
  72. message m;
  73. while( ( m = receiveMessage() ).id != IdQuit )
  74. {
  75. pthread_mutex_lock( &m_master->mutex );
  76. processMessage( m );
  77. pthread_mutex_unlock( &m_master->mutex );
  78. }
  79. m_guiExit = true;
  80. }
  81. virtual bool processMessage( const message & _m )
  82. {
  83. switch( _m.id )
  84. {
  85. case IdQuit:
  86. break;
  87. case IdShowUI:
  88. case IdHideUI:
  89. case IdLoadSettingsFromFile:
  90. case IdLoadPresetFile:
  91. pthread_mutex_lock( &m_guiMutex );
  92. m_guiMessages.push( _m );
  93. pthread_mutex_unlock( &m_guiMutex );
  94. break;
  95. case IdSaveSettingsToFile:
  96. {
  97. LocalZynAddSubFx::saveXML( _m.getString() );
  98. sendMessage( IdSaveSettingsToFile );
  99. break;
  100. }
  101. case IdZasfPresetDirectory:
  102. LocalZynAddSubFx::setPresetDir( _m.getString() );
  103. break;
  104. case IdZasfLmmsWorkingDirectory:
  105. LocalZynAddSubFx::setLmmsWorkingDir( _m.getString() );
  106. break;
  107. case IdZasfSetPitchWheelBendRange:
  108. LocalZynAddSubFx::setPitchWheelBendRange( _m.getInt() );
  109. break;
  110. default:
  111. return RemotePluginClient::processMessage( _m );
  112. }
  113. return true;
  114. }
  115. // all functions are called while m_master->mutex is held
  116. virtual void processMidiEvent( const MidiEvent& event, const f_cnt_t /* _offset */ )
  117. {
  118. LocalZynAddSubFx::processMidiEvent( event );
  119. }
  120. virtual void process( const sampleFrame * _in, sampleFrame * _out )
  121. {
  122. LocalZynAddSubFx::processAudio( _out );
  123. }
  124. static void * messageLoop( void * _arg )
  125. {
  126. RemoteZynAddSubFx * _this =
  127. static_cast<RemoteZynAddSubFx *>( _arg );
  128. _this->messageLoop();
  129. return NULL;
  130. }
  131. void guiLoop();
  132. private:
  133. const int m_guiSleepTime;
  134. pthread_t m_messageThreadHandle;
  135. pthread_mutex_t m_guiMutex;
  136. std::queue<RemotePluginClient::message> m_guiMessages;
  137. bool m_guiExit;
  138. } ;
  139. void RemoteZynAddSubFx::guiLoop()
  140. {
  141. int exitProgram = 0;
  142. MasterUI * ui = NULL;
  143. while( !m_guiExit )
  144. {
  145. if( ui )
  146. {
  147. Fl::wait( m_guiSleepTime / 1000.0 );
  148. }
  149. else
  150. {
  151. #ifdef LMMS_BUILD_WIN32
  152. Sleep( m_guiSleepTime );
  153. #else
  154. usleep( m_guiSleepTime*1000 );
  155. #endif
  156. }
  157. if( exitProgram == 1 )
  158. {
  159. pthread_mutex_lock( &m_master->mutex );
  160. sendMessage( IdHideUI );
  161. exitProgram = 0;
  162. pthread_mutex_unlock( &m_master->mutex );
  163. }
  164. pthread_mutex_lock( &m_guiMutex );
  165. while( m_guiMessages.size() )
  166. {
  167. RemotePluginClient::message m = m_guiMessages.front();
  168. m_guiMessages.pop();
  169. switch( m.id )
  170. {
  171. case IdShowUI:
  172. // we only create GUI
  173. if( !ui )
  174. {
  175. Fl::scheme( "plastic" );
  176. ui = new MasterUI( m_master, &exitProgram );
  177. }
  178. ui->showUI();
  179. ui->refresh_master_ui();
  180. break;
  181. case IdLoadSettingsFromFile:
  182. {
  183. LocalZynAddSubFx::loadXML( m.getString() );
  184. if( ui )
  185. {
  186. ui->refresh_master_ui();
  187. }
  188. pthread_mutex_lock( &m_master->mutex );
  189. sendMessage( IdLoadSettingsFromFile );
  190. pthread_mutex_unlock( &m_master->mutex );
  191. break;
  192. }
  193. case IdLoadPresetFile:
  194. {
  195. LocalZynAddSubFx::loadPreset( m.getString(), ui ?
  196. ui->npartcounter->value()-1 : 0 );
  197. if( ui )
  198. {
  199. ui->npartcounter->do_callback();
  200. ui->updatepanel();
  201. ui->refresh_master_ui();
  202. }
  203. pthread_mutex_lock( &m_master->mutex );
  204. sendMessage( IdLoadPresetFile );
  205. pthread_mutex_unlock( &m_master->mutex );
  206. break;
  207. }
  208. default:
  209. break;
  210. }
  211. }
  212. pthread_mutex_unlock( &m_guiMutex );
  213. }
  214. Fl::flush();
  215. delete ui;
  216. }
  217. int main( int _argc, char * * _argv )
  218. {
  219. #ifdef SYNC_WITH_SHM_FIFO
  220. if( _argc < 3 )
  221. #else
  222. if( _argc < 2 )
  223. #endif
  224. {
  225. fprintf( stderr, "not enough arguments\n" );
  226. return -1;
  227. }
  228. #ifdef LMMS_BUILD_WIN32
  229. #ifndef __WINPTHREADS_VERSION
  230. // (non-portable) initialization of statically linked pthread library
  231. pthread_win32_process_attach_np();
  232. pthread_win32_thread_attach_np();
  233. #endif
  234. #endif
  235. #ifdef SYNC_WITH_SHM_FIFO
  236. RemoteZynAddSubFx * remoteZASF =
  237. new RemoteZynAddSubFx( atoi( _argv[1] ), atoi( _argv[2] ) );
  238. #else
  239. RemoteZynAddSubFx * remoteZASF = new RemoteZynAddSubFx( _argv[1] );
  240. #endif
  241. remoteZASF->guiLoop();
  242. delete remoteZASF;
  243. #ifdef LMMS_BUILD_WIN32
  244. #ifndef __WINPTHREADS_VERSION
  245. pthread_win32_thread_detach_np();
  246. pthread_win32_process_detach_np();
  247. #endif
  248. #endif
  249. return 0;
  250. }
  251. #ifdef NTK_GUI
  252. static Fl_Tiled_Image *module_backdrop;
  253. #endif
  254. void set_module_parameters ( Fl_Widget *o )
  255. {
  256. #ifdef NTK_GUI
  257. o->box( FL_DOWN_FRAME );
  258. o->align( o->align() | FL_ALIGN_IMAGE_BACKDROP );
  259. o->color( FL_BLACK );
  260. o->image( module_backdrop );
  261. o->labeltype( FL_SHADOW_LABEL );
  262. #else
  263. o->box( FL_PLASTIC_UP_BOX );
  264. o->color( FL_CYAN );
  265. o->labeltype( FL_EMBOSSED_LABEL );
  266. #endif
  267. }