123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324 |
- /*
- * RemoteZynAddSubFx.cpp - ZynAddSubFx-embedding plugin
- *
- * Copyright (c) 2008-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
- *
- * This file is part of LMMS - https://lmms.io
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program (see COPYING); if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA.
- *
- */
- #include <lmmsconfig.h>
- #ifdef LMMS_BUILD_WIN32
- #include <winsock2.h>
- #endif
- #include <queue>
- #include <FL/x.H>
- #undef CursorShape // is, by mistake, not undefed in FL
- #define BUILD_REMOTE_PLUGIN_CLIENT
- #include "RemotePlugin.h"
- #include "RemoteZynAddSubFx.h"
- #include "LocalZynAddSubFx.h"
- #include "zynaddsubfx/src/Nio/Nio.h"
- #include "zynaddsubfx/src/UI/MasterUI.h"
- class RemoteZynAddSubFx : public RemotePluginClient, public LocalZynAddSubFx
- {
- public:
- #ifdef SYNC_WITH_SHM_FIFO
- RemoteZynAddSubFx( int _shm_in, int _shm_out ) :
- RemotePluginClient( _shm_in, _shm_out ),
- #else
- RemoteZynAddSubFx( const char * socketPath ) :
- RemotePluginClient( socketPath ),
- #endif
- LocalZynAddSubFx(),
- m_guiSleepTime( 100 ),
- m_guiExit( false )
- {
- Nio::start();
- setInputCount( 0 );
- sendMessage( IdInitDone );
- waitForMessage( IdInitDone );
- pthread_mutex_init( &m_guiMutex, nullptr );
- pthread_create( &m_messageThreadHandle, nullptr, messageLoop, this );
- }
- virtual ~RemoteZynAddSubFx()
- {
- Nio::stop();
- }
- virtual void updateSampleRate()
- {
- LocalZynAddSubFx::setSampleRate( sampleRate() );
- }
- virtual void updateBufferSize()
- {
- LocalZynAddSubFx::setBufferSize( bufferSize() );
- }
- void messageLoop()
- {
- message m;
- while( ( m = receiveMessage() ).id != IdQuit )
- {
- pthread_mutex_lock( &m_master->mutex );
- processMessage( m );
- pthread_mutex_unlock( &m_master->mutex );
- }
- m_guiExit = true;
- }
- virtual bool processMessage( const message & _m )
- {
- switch( _m.id )
- {
- case IdQuit:
- break;
- case IdShowUI:
- case IdHideUI:
- case IdLoadSettingsFromFile:
- case IdLoadPresetFile:
- pthread_mutex_lock( &m_guiMutex );
- m_guiMessages.push( _m );
- pthread_mutex_unlock( &m_guiMutex );
- break;
- case IdSaveSettingsToFile:
- {
- LocalZynAddSubFx::saveXML( _m.getString() );
- sendMessage( IdSaveSettingsToFile );
- break;
- }
- case IdZasfPresetDirectory:
- LocalZynAddSubFx::setPresetDir( _m.getString() );
- break;
- case IdZasfLmmsWorkingDirectory:
- LocalZynAddSubFx::setLmmsWorkingDir( _m.getString() );
- break;
- case IdZasfSetPitchWheelBendRange:
- LocalZynAddSubFx::setPitchWheelBendRange( _m.getInt() );
- break;
- default:
- return RemotePluginClient::processMessage( _m );
- }
- return true;
- }
- // all functions are called while m_master->mutex is held
- virtual void processMidiEvent( const MidiEvent& event, const f_cnt_t /* _offset */ )
- {
- LocalZynAddSubFx::processMidiEvent( event );
- }
- virtual void process( const sampleFrame * _in, sampleFrame * _out )
- {
- LocalZynAddSubFx::processAudio( _out );
- }
- static void * messageLoop( void * _arg )
- {
- RemoteZynAddSubFx * _this =
- static_cast<RemoteZynAddSubFx *>( _arg );
- _this->messageLoop();
- return nullptr;
- }
- void guiLoop();
- private:
- const int m_guiSleepTime;
- pthread_t m_messageThreadHandle;
- pthread_mutex_t m_guiMutex;
- std::queue<RemotePluginClient::message> m_guiMessages;
- bool m_guiExit;
- } ;
- void RemoteZynAddSubFx::guiLoop()
- {
- int exitProgram = 0;
- MasterUI * ui = nullptr;
- while( !m_guiExit )
- {
- if( ui )
- {
- Fl::wait( m_guiSleepTime / 1000.0 );
- }
- else
- {
- #ifdef LMMS_BUILD_WIN32
- Sleep( m_guiSleepTime );
- #else
- usleep( m_guiSleepTime*1000 );
- #endif
- }
- if( exitProgram == 1 )
- {
- pthread_mutex_lock( &m_master->mutex );
- sendMessage( IdHideUI );
- exitProgram = 0;
- pthread_mutex_unlock( &m_master->mutex );
- }
- pthread_mutex_lock( &m_guiMutex );
- while( m_guiMessages.size() )
- {
- RemotePluginClient::message m = m_guiMessages.front();
- m_guiMessages.pop();
- switch( m.id )
- {
- case IdShowUI:
- // we only create GUI
- if( !ui )
- {
- Fl::scheme( "plastic" );
- ui = new MasterUI( m_master, &exitProgram );
- }
- ui->showUI();
- ui->refresh_master_ui();
- break;
- case IdLoadSettingsFromFile:
- {
- LocalZynAddSubFx::loadXML( m.getString() );
- if( ui )
- {
- ui->refresh_master_ui();
- }
- pthread_mutex_lock( &m_master->mutex );
- sendMessage( IdLoadSettingsFromFile );
- pthread_mutex_unlock( &m_master->mutex );
- break;
- }
- case IdLoadPresetFile:
- {
- LocalZynAddSubFx::loadPreset( m.getString(), ui ?
- ui->npartcounter->value()-1 : 0 );
- if( ui )
- {
- ui->npartcounter->do_callback();
- ui->updatepanel();
- ui->refresh_master_ui();
- }
- pthread_mutex_lock( &m_master->mutex );
- sendMessage( IdLoadPresetFile );
- pthread_mutex_unlock( &m_master->mutex );
- break;
- }
- default:
- break;
- }
- }
- pthread_mutex_unlock( &m_guiMutex );
- }
- Fl::flush();
- delete ui;
- }
- int main( int _argc, char * * _argv )
- {
- #ifdef SYNC_WITH_SHM_FIFO
- if( _argc < 3 )
- #else
- if( _argc < 2 )
- #endif
- {
- fprintf( stderr, "not enough arguments\n" );
- return -1;
- }
- #ifdef LMMS_BUILD_WIN32
- #ifndef __WINPTHREADS_VERSION
- // (non-portable) initialization of statically linked pthread library
- pthread_win32_process_attach_np();
- pthread_win32_thread_attach_np();
- #endif
- #endif
- #ifdef SYNC_WITH_SHM_FIFO
- RemoteZynAddSubFx * remoteZASF =
- new RemoteZynAddSubFx( atoi( _argv[1] ), atoi( _argv[2] ) );
- #else
- RemoteZynAddSubFx * remoteZASF = new RemoteZynAddSubFx( _argv[1] );
- #endif
- remoteZASF->guiLoop();
- delete remoteZASF;
- #ifdef LMMS_BUILD_WIN32
- #ifndef __WINPTHREADS_VERSION
- pthread_win32_thread_detach_np();
- pthread_win32_process_detach_np();
- #endif
- #endif
- return 0;
- }
- #ifdef NTK_GUI
- static Fl_Tiled_Image *module_backdrop;
- #endif
- void set_module_parameters ( Fl_Widget *o )
- {
- #ifdef NTK_GUI
- o->box( FL_DOWN_FRAME );
- o->align( o->align() | FL_ALIGN_IMAGE_BACKDROP );
- o->color( FL_BLACK );
- o->image( module_backdrop );
- o->labeltype( FL_SHADOW_LABEL );
- #else
- o->box( FL_PLASTIC_UP_BOX );
- o->color( FL_CYAN );
- o->labeltype( FL_EMBOSSED_LABEL );
- #endif
- }
|