From 5b98f07f227c9886ef80d122897b73da0e36ffe5 Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Wed, 3 Sep 2008 16:07:15 +0000 Subject: [PATCH] rewrote VST support layer to use the new remotePlugin-framework git-svn-id: https://lmms.svn.sf.net/svnroot/lmms/trunk/lmms@1542 0778d3d1-df1d-0410-868b-ea421aaaa00d --- ChangeLog | 23 + include/aeffectx.h | 4 +- plugins/vestige/vestige.cpp | 14 +- plugins/vestige/vestige.h | 4 +- plugins/vst_base/CMakeLists.txt | 13 +- plugins/vst_base/communication.h | 132 +----- plugins/vst_base/remote_vst_plugin.cpp | 620 +++++++++++-------------- plugins/vst_base/vst_plugin.cpp | 485 ++++--------------- plugins/vst_base/vst_plugin.h | 101 +--- plugins/vst_effect/vst_effect.cpp | 12 +- plugins/vst_effect/vst_effect.h | 4 +- 11 files changed, 439 insertions(+), 973 deletions(-) diff --git a/ChangeLog b/ChangeLog index f9877ec9a..52f9712f4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,26 @@ +2008-09-03 Tobias Doerffel + + * plugins/vst_base/communication.h: + * plugins/vst_base/vst_plugin.h: + * plugins/vst_base/vst_plugin.cpp: + * plugins/vst_base/remote_vst_plugin.cpp: + * plugins/vst_base/CMakeLists.txt: + * plugins/vst_effect/vst_effect.h: + * plugins/vst_effect/vst_effect.cpp: + * plugins/vestige/vestige.h: + * plugins/vestige/vestige.cpp: + * include/aeffectx.h: + rewrote VST support layer to use the new remotePlugin-framework + + * include/remote_plugin.h: + * src/core/remote_plugin.cpp: + - added channel splitting mode + - made initial wait optional + - messages now can be constructed and set inline + + * CMakeLists.txt: + added hint about removing CMakeCache.txt when libsndfile is missing + 2008-09-02 Tobias Doerffel * cmake/modules/Win32Toolchain.cmake: diff --git a/include/aeffectx.h b/include/aeffectx.h index 896f969d2..7b524a509 100644 --- a/include/aeffectx.h +++ b/include/aeffectx.h @@ -118,7 +118,7 @@ int kVstTempoValid = 1 << 10; int kVstTransportPlaying = 1 << 1; -class VSTPlugin; +class remoteVstPlugin; class VstMidiEvent @@ -221,7 +221,7 @@ public: // flags 24-27 int flags; // Fill somewhere 28-2b - VSTPlugin * user; + remoteVstPlugin * user; // Zeroes 2c-2f 30-33 34-37 38-3b char empty3[4 + 4 + 4 + 4]; // 1.0f 3c-3f diff --git a/plugins/vestige/vestige.cpp b/plugins/vestige/vestige.cpp index bf381c744..78ed7016f 100644 --- a/plugins/vestige/vestige.cpp +++ b/plugins/vestige/vestige.cpp @@ -35,7 +35,7 @@ #include "gui_templates.h" #include "instrument_play_handle.h" #include "instrument_track.h" -#include "lvsl_client.h" +#include "vst_plugin.h" #include "note_play_handle.h" #include "pixmap_button.h" #include "song.h" @@ -153,7 +153,7 @@ void vestigeInstrument::setParameter( const QString & _param, PLUGIN_NAME::getIconPixmap( "logo", 24, 24 ), 0 ); m_pluginMutex.lock(); - m_plugin = new remoteVSTPlugin( m_pluginDLL ); + m_plugin = new vstPlugin( m_pluginDLL ); if( m_plugin->failed() ) { m_pluginMutex.unlock(); @@ -263,11 +263,11 @@ void vestigeInstrument::playNote( notePlayHandle * _n, bool, sampleFrame * ) const int k = getInstrumentTrack()->masterKey( _n ); if( m_runningNotes[k] > 0 ) { - m_plugin->enqueueMidiEvent( midiEvent( MidiNoteOff, 0, + m_plugin->processMidiEvent( midiEvent( MidiNoteOff, 0, k, 0 ), 0 ); } ++m_runningNotes[k]; - m_plugin->enqueueMidiEvent( midiEvent( MidiNoteOn, 0, k, + m_plugin->processMidiEvent( midiEvent( MidiNoteOn, 0, k, _n->getVolume() ), _n->offset() ); // notify when the handle stops, call to deleteNotePluginData _n->m_pluginData = _n; @@ -286,7 +286,7 @@ void vestigeInstrument::deleteNotePluginData( notePlayHandle * _n ) const int k = getInstrumentTrack()->masterKey( _n ); if( --m_runningNotes[k] <= 0 ) { - m_plugin->enqueueMidiEvent( + m_plugin->processMidiEvent( midiEvent( MidiNoteOff, 0, k, 0 ), 0 ); } } @@ -302,7 +302,7 @@ bool vestigeInstrument::handleMidiEvent( const midiEvent & _me, m_pluginMutex.lock(); if( m_plugin != NULL ) { - m_plugin->enqueueMidiEvent( _me, _time ); + m_plugin->processMidiEvent( _me, _time ); } m_pluginMutex.unlock(); return( TRUE ); @@ -489,7 +489,7 @@ void vestigeInstrumentView::noteOffAll( void ) { for( int key = 0; key < NumKeys; ++key ) { - m_vi->m_plugin->enqueueMidiEvent( + m_vi->m_plugin->processMidiEvent( midiEvent( MidiNoteOff, 0, key, 0 ), 0 ); } } diff --git a/plugins/vestige/vestige.h b/plugins/vestige/vestige.h index 927487464..dee258abb 100644 --- a/plugins/vestige/vestige.h +++ b/plugins/vestige/vestige.h @@ -40,7 +40,7 @@ class QPixmap; class QPushButton; class pixmapButton; -class remoteVSTPlugin; +class vstPlugin; class vestigeInstrument : public instrument @@ -90,7 +90,7 @@ private: int m_runningNotes[NumKeys]; - remoteVSTPlugin * m_plugin; + vstPlugin * m_plugin; QMutex m_pluginMutex; QString m_pluginDLL; diff --git a/plugins/vst_base/CMakeLists.txt b/plugins/vst_base/CMakeLists.txt index 258020dcb..4a6d25edc 100644 --- a/plugins/vst_base/CMakeLists.txt +++ b/plugins/vst_base/CMakeLists.txt @@ -2,22 +2,21 @@ IF(LMMS_HAVE_VST) INCLUDE(BuildPlugin) -BUILD_PLUGIN(vstbase vst_base.cpp lvsl_client.cpp lvsl_client.h communication.h MOCFILES lvsl_client.h) -SET_TARGET_PROPERTIES(vstbase PROPERTIES COMPILE_FLAGS "-D_FORTIFY_SOURCE=0") +BUILD_PLUGIN(vstbase vst_base.cpp vst_plugin.cpp vst_plugin.h communication.h MOCFILES vst_plugin.h) IF(LMMS_HOST_X86_64) SET(EXTRA_FLAGS -m32 -Wb,--as-cmd='as --32',--ld-cmd='ld -melf_i386' -L/usr/lib32) ENDIF(LMMS_HOST_X86_64) ADD_CUSTOM_COMMAND( - SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/lvsl_server.cpp + SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/remote_vst_plugin.cpp COMMAND wineg++ - ARGS -I${CMAKE_BINARY_DIR} -I${CMAKE_SOURCE_DIR}/include -I${CMAKE_INSTALL_PREFIX}/include/wine/windows -I/usr/include/wine/windows ${CMAKE_CURRENT_SOURCE_DIR}/lvsl_server.cpp -mwindows -lpthread ${EXTRA_FLAGS} -o lvsl_server + ARGS -I${CMAKE_BINARY_DIR} -I${CMAKE_SOURCE_DIR}/include -I${CMAKE_INSTALL_PREFIX}/include/wine/windows -I/usr/include/wine/windows ${CMAKE_CURRENT_SOURCE_DIR}/remote_vst_plugin.cpp -mwindows -lpthread ${EXTRA_FLAGS} -o remote_vst_plugin TARGET vstbase - OUTPUTS lvsl_server.exe.so + OUTPUTS remote_vst_plugin ) -SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES lvsl_server.exe.so) +SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES remote_vst_plugin.exe.so) -INSTALL(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/lvsl_server ${CMAKE_CURRENT_BINARY_DIR}/lvsl_server.exe.so DESTINATION ${PLUGIN_DIR}) +INSTALL(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/remote_vst_plugin ${CMAKE_CURRENT_BINARY_DIR}/remote_vst_plugin.exe.so DESTINATION ${PLUGIN_DIR}) ENDIF(LMMS_HAVE_VST) diff --git a/plugins/vst_base/communication.h b/plugins/vst_base/communication.h index c20eca082..a299798e6 100644 --- a/plugins/vst_base/communication.h +++ b/plugins/vst_base/communication.h @@ -27,84 +27,19 @@ #ifndef _COMMUNICATION_H #define _COMMUNICATION_H -#include "lmmsconfig.h" - -#ifdef LMMS_HAVE_UNISTD_H -#include -#endif - -#include - - -template -inline T readValue( int _fd = 0 ) -{ - T i; - read( _fd, &i, sizeof( i ) ); - return( i ); -} - - - - -template -inline void writeValue( const T & _i, int _fd = 1 ) -{ - write( _fd, &_i, sizeof( _i ) ); -} - - - - -static inline std::string readString( int _fd = 0 ) -{ - Sint16 len = readValue( _fd ); - char * sc = new char[len + 1]; - read( _fd, sc, len ); - sc[len] = '\0'; - std::string s( sc ); - delete[] sc; - return( s ); -} - - - - -static inline void writeString( const char * _str, int _fd = 1 ) -{ - int len = strlen( _str ); - writeValue( len, _fd ); - write( _fd, _str, len ); -} - - +#include "remote_plugin.h" struct vstParameterDumpItem { - Sint32 index; - char shortLabel[8]; + int32_t index; + std::string shortLabel; float value; } ; - -// summarized version of VstParameterProperties-struct - useful because client -// doesn't have to know about the latter one -struct vstParamProperties -{ - char label[64]; - char shortLabel[8]; - char categoryLabel[24]; - float minValue; - float maxValue; - float step; - Sint16 category; -} ; - - -enum hostLanguages +enum VstHostLanguages { LanguageEnglish = 1, LanguageGerman, @@ -116,49 +51,32 @@ enum hostLanguages -enum vstRemoteCommands +enum VstRemoteMessageIDs { - // client -> server - VST_LOAD_PLUGIN = 0, - VST_CLOSE_PLUGIN, - VST_SHOW_EDITOR, - VST_PROCESS, - VST_ENQUEUE_MIDI_EVENT, - VST_SAMPLE_RATE, - VST_BUFFER_SIZE, - VST_BPM, - VST_LANGUAGE, - VST_GET_PARAMETER_COUNT = 20, - VST_GET_PARAMETER_DUMP, - VST_SET_PARAMETER_DUMP, - VST_GET_PARAMETER_PROPERTIES, + // vstPlugin -> remoteVstPlugin + IdVstLoadPlugin = IdUserBase, + IdVstClosePlugin, + IdVstSetTempo, + IdVstSetLanguage, + IdVstGetParameterCount, + IdVstGetParameterDump, + IdVstSetParameterDump, + IdVstGetParameterProperties, - // server -> client - VST_INITIALIZATION_DONE = 100, - VST_FAILED_LOADING_PLUGIN, - VST_QUIT_ACK, - VST_SHM_KEY_AND_SIZE, - VST_INPUT_COUNT, - VST_OUTPUT_COUNT, - VST_PLUGIN_XID, - VST_PLUGIN_EDITOR_GEOMETRY, - VST_PROCESS_DONE, - VST_PLUGIN_NAME, - VST_PLUGIN_VERSION, - VST_PLUGIN_VENDOR_STRING, - VST_PLUGIN_PRODUCT_STRING, - VST_PARAMETER_COUNT, - VST_PARAMETER_DUMP, - VST_PARAMETER_PROPERTIES, - VST_GET_SAMPLE_RATE = 120, - VST_GET_BUFFER_SIZE, - - VST_DEBUG_MSG = 200, - VST_UNDEFINED_CMD + // remoteVstPlugin -> vstPlugin + IdVstFailedLoadingPlugin, + IdVstPluginWindowID, + IdVstPluginEditorGeometry, + IdVstPluginName, + IdVstPluginVersion, + IdVstPluginVendorString, + IdVstPluginProductString, + IdVstParameterCount, + IdVstParameterDump, + IdVstParameterProperties } ; - #endif diff --git a/plugins/vst_base/remote_vst_plugin.cpp b/plugins/vst_base/remote_vst_plugin.cpp index 26d6fcf23..10a900dcf 100644 --- a/plugins/vst_base/remote_vst_plugin.cpp +++ b/plugins/vst_base/remote_vst_plugin.cpp @@ -30,30 +30,14 @@ #include "lmmsconfig.h" +#define BUILD_REMOTE_PLUGIN_CLIENT + +#include "remote_plugin.h" + #ifdef LMMS_HAVE_PTHREAD_H #include #endif -#ifdef LMMS_HAVE_SYS_TYPES_H -#include -#endif - -#ifdef LMMS_HAVE_SYS_IPC_H -#include -#endif - -#ifdef LMMS_HAVE_SYS_SHM_H -#include -#endif - -#ifdef LMMS_HAVE_STDARG_H -#include -#endif - -#ifdef LMMS_HAVE_SIGNAL_H -#include -#endif - #ifdef LMMS_HAVE_SCHED_H #include #endif @@ -101,36 +85,23 @@ static pthread_key_t ejmpbuf_key; #endif -static hostLanguages hlang = LanguageEnglish; +static VstHostLanguages hlang = LanguageEnglish; -class VSTPlugin; +class remoteVstPlugin; -VSTPlugin * plugin = NULL; - - - -void lvsMessage( const char * _fmt, ... ) -{ - va_list ap; - char buffer[512]; - - va_start( ap, _fmt ); - vsnprintf( buffer, sizeof( buffer ), _fmt, ap ); - writeValue( VST_DEBUG_MSG, 1 ); - writeString( buffer, 1 ); - va_end( ap ); -} +remoteVstPlugin * __plugin = NULL; -class VSTPlugin +class remoteVstPlugin : public remotePluginClient { public: - VSTPlugin( void ); + remoteVstPlugin( key_t _shm_in, key_t _shm_out ); + virtual ~remoteVstPlugin(); - ~VSTPlugin(); + virtual bool processMessage( const message & _m ); void init( const std::string & _plugin_file ); @@ -143,23 +114,33 @@ public: } } - void process( void ); + virtual bool process( const sampleFrame * _in, sampleFrame * _out ); - // enqueue given MIDI-event to be processed the next time process() is - // called - void enqueueMidiEvent( const midiEvent & _event, - const f_cnt_t _frames_ahead ); + + virtual void processMidiEvent( const midiEvent & _event, + const f_cnt_t _offset ); // set given sample-rate for plugin - void setSampleRate( const sample_rate_t _rate ) + void updateSampleRate( void ) { - m_plugin->dispatcher( m_plugin, effSetSampleRate, 0, 0, NULL, - (float) _rate ); - m_sampleRate = _rate; + if( m_plugin ) + { + m_plugin->dispatcher( m_plugin, effSetSampleRate, 0, 0, + NULL, (float) sampleRate() ); + } } - // set given block-size for plugin - void setBlockSize( const fpp_t _bsize ); + // set given buffer-size for plugin + void updateBufferSize( void ) + { + if( m_plugin ) + { + m_plugin->dispatcher( m_plugin, effSetBlockSize, 0, + bufferSize(), NULL, 0.0f ); + } + } + + // set given tempo void setBPM( const bpm_t _bpm ) @@ -168,7 +149,7 @@ public: } // determine VST-version the plugin uses - Sint32 pluginVersion( void ) const + int pluginVersion( void ) const { return( m_plugin->dispatcher( m_plugin, effGetVendorVersion, 0, 0, NULL, 0.0f ) ); @@ -184,30 +165,28 @@ public: const char * pluginProductString( void ) const; // do a complete parameter-dump and post it - void getParameterDump( void ) const; + void getParameterDump( void ); // read parameter-dump and set it for plugin - void setParameterDump( void ); + void setParameterDump( const message & _m ); // post properties of specified parameter - void getParameterProperties( const Sint32 _idx ); + void getParameterProperties( const int _idx ); // number of inputs - ch_cnt_t inputCount( void ) const + virtual int inputCount( void ) const { return( m_plugin->numInputs ); } // number of outputs - ch_cnt_t outputCount( void ) const + virtual int outputCount( void ) const { return( m_plugin->numOutputs ); } - // called once at initialization and everytime number of inputs/outputs - // or block-size changes and is responsible for resizing shared memory - // and inform client about changed shm-keys, input/output-count etc. - void resizeSharedMemory( void ); + // has to be called as soon as input- or output-count changes + void updateInOutCount( void ); private: @@ -233,25 +212,21 @@ private: AEffect * m_plugin; HWND m_window; - Sint32 m_windowXID; - Sint16 m_windowWidth; - Sint16 m_windowHeight; + Sint32 m_windowID; + int m_windowWidth; + int m_windowHeight; pthread_mutex_t m_lock; pthread_cond_t m_windowStatusChange; DWORD m_guiThreadID; - fpp_t m_blockSize; - float * m_shm; - float * * m_inputs; float * * m_outputs; std::list m_midiEvents; bpm_t m_bpm; - sample_rate_t m_sampleRate; double m_currentSamplePos; } ; @@ -259,98 +234,30 @@ private: -VSTPlugin::VSTPlugin( void ) : +remoteVstPlugin::remoteVstPlugin( key_t _shm_in, key_t _shm_out ) : + remotePluginClient( _shm_in, _shm_out ), m_shortName( "" ), m_libInst( NULL ), m_plugin( NULL ), m_window( NULL ), - m_windowXID( 0 ), + m_windowID( 0 ), m_windowWidth( 0 ), m_windowHeight( 0 ), m_lock(), m_windowStatusChange(), m_guiThreadID( 0 ), - m_blockSize( 0 ), - m_shm( NULL ), m_inputs( NULL ), m_outputs( NULL ), m_midiEvents(), m_bpm( 0 ), - m_sampleRate( 44100 ), m_currentSamplePos( 0 ) { } - -void VSTPlugin::init( const std::string & _plugin_file ) +remoteVstPlugin::~remoteVstPlugin() { - if( load( _plugin_file ) == false ) - { - writeValue( VST_FAILED_LOADING_PLUGIN ); - return; - } - - /* set program to zero */ - /* i comment this out because it breaks dfx Geometer - * looks like we cant set programs for it - * - m_plugin->dispatcher( m_plugin, effSetProgram, 0, 0, NULL, 0.0f); */ - // request rate and blocksize - writeValue( VST_GET_SAMPLE_RATE ); - writeValue( VST_GET_BUFFER_SIZE ); - - - m_plugin->dispatcher( m_plugin, effMainsChanged, 0, 1, NULL, 0.0f ); - - - if( CreateThread( NULL, 0, guiEventLoop, this, 0, NULL ) == NULL ) - { - lvsMessage( "could not create GUI-thread" ); - return; - } - pthread_cond_wait( &m_windowStatusChange, &m_lock); - - - // now post some information about our plugin - writeValue( VST_PLUGIN_XID ); - writeValue( m_windowXID ); - - if( m_windowXID != 0 ) - { - writeValue( VST_PLUGIN_EDITOR_GEOMETRY ); - writeValue( m_windowWidth ); - writeValue( m_windowHeight ); - } - - writeValue( VST_PLUGIN_NAME ); - writeString( pluginName() ); - - writeValue( VST_PLUGIN_VERSION ); - writeValue( pluginVersion() ); - - writeValue( VST_PLUGIN_VENDOR_STRING ); - writeString( pluginVendorString() ); - - writeValue( VST_PLUGIN_PRODUCT_STRING ); - writeString( pluginProductString() ); - - writeValue( VST_PARAMETER_COUNT ); - writeValue( (Sint32) m_plugin->numParams ); - - // tell client that we've done everything so far - writeValue( VST_INITIALIZATION_DONE ); -} - - - - -VSTPlugin::~VSTPlugin() -{ - // acknowledge quit - writeValue( VST_QUIT_ACK ); - if( m_window != NULL ) { // notify GUI-thread @@ -373,17 +280,105 @@ VSTPlugin::~VSTPlugin() delete[] m_inputs; delete[] m_outputs; - - if( m_shm != NULL ) - { - shmdt( m_shm ); - } } -bool VSTPlugin::load( const std::string & _plugin_file ) +bool remoteVstPlugin::processMessage( const message & _m ) +{ + switch( _m.id ) + { + case IdVstLoadPlugin: + init( _m.getString() ); + break; + + case IdShowUI: + showEditor(); + break; + + case IdVstSetTempo: + setBPM( _m.getInt() ); + break; + + case IdVstSetLanguage: + hlang = static_cast( _m.getInt() ); + break; + + case IdVstGetParameterDump: + getParameterDump(); + break; + + case IdVstSetParameterDump: + setParameterDump( _m ); + break; + + case IdVstGetParameterProperties: + getParameterProperties( _m.getInt() ); + break; + + default: + return remotePluginClient::processMessage( _m ); + } + return true; +} + + + +void remoteVstPlugin::init( const std::string & _plugin_file ) +{ + if( load( _plugin_file ) == false ) + { + sendMessage( IdVstFailedLoadingPlugin ); + return; + } + + updateInOutCount(); + + /* set program to zero */ + /* i comment this out because it breaks dfx Geometer + * looks like we cant set programs for it + * + m_plugin->dispatcher( m_plugin, effSetProgram, 0, 0, NULL, 0.0f); */ + // request rate and blocksize + + m_plugin->dispatcher( m_plugin, effMainsChanged, 0, 1, NULL, 0.0f ); + + + if( CreateThread( NULL, 0, guiEventLoop, this, 0, NULL ) == NULL ) + { + fprintf( stderr, "could not create GUI-thread\n" ); + return; + } + pthread_cond_wait( &m_windowStatusChange, &m_lock); + + + // now post some information about our plugin + sendMessage( message( IdVstPluginWindowID ).addInt( m_windowID ) ); + + if( m_windowID != 0 ) + { + sendMessage( message( IdVstPluginEditorGeometry ). + addInt( m_windowWidth ). + addInt( m_windowHeight ) ); + } + + sendMessage( message( IdVstPluginName ).addString( pluginName() ) ); + sendMessage( message( IdVstPluginVersion ).addInt( pluginVersion() ) ); + sendMessage( message( IdVstPluginVendorString ). + addString( pluginVendorString() ) ); + sendMessage( message( IdVstPluginProductString ). + addString( pluginProductString() ) ); + sendMessage( message( IdVstParameterCount ). + addInt( m_plugin->numParams ) ); + + sendMessage( IdInitDone ); +} + + + + +bool remoteVstPlugin::load( const std::string & _plugin_file ) { if( ( m_libInst = LoadLibraryA( _plugin_file.c_str() ) ) == NULL ) @@ -413,7 +408,8 @@ bool VSTPlugin::load( const std::string & _plugin_file ) if( m_plugin->magic != kEffectMagic ) { - lvsMessage( "%s is not a VST plugin\n", _plugin_file.c_str() ); + fprintf( stderr, "%s is not a VST plugin\n", + _plugin_file.c_str() ); } m_plugin->dispatcher( m_plugin, effOpen, 0, 0, 0, 0 ); @@ -423,7 +419,7 @@ bool VSTPlugin::load( const std::string & _plugin_file ) -void VSTPlugin::process( void ) +bool remoteVstPlugin::process( const sampleFrame * _in, sampleFrame * _out ) { // first we gonna post all MIDI-events we enqueued so far if( m_midiEvents.size() ) @@ -440,7 +436,7 @@ void VSTPlugin::process( void ) VstEvents * events = (VstEvents *) event_buf; events->reserved = 0; events->numEvents = m_midiEvents.size(); - Sint16 idx = 0; + int idx = 0; for( std::list::iterator it = m_midiEvents.begin(); it != m_midiEvents.end(); ++it, ++idx ) @@ -456,36 +452,33 @@ void VSTPlugin::process( void ) // now we're ready to fetch sound from VST-plugin - for( ch_cnt_t i = 0; i < inputCount(); ++i ) + for( int i = 0; i < inputCount(); ++i ) { - m_inputs[i] = &m_shm[i * m_blockSize]; + m_inputs[i] = &((float *) _in)[i * bufferSize()]; } - for( ch_cnt_t i = 0; i < outputCount(); ++i ) + for( int i = 0; i < outputCount(); ++i ) { - m_outputs[i] = &m_shm[( i + inputCount() ) * m_blockSize]; - memset( m_outputs[i], 0, m_blockSize * sizeof( float ) ); + m_outputs[i] = &((float *) _out)[i * bufferSize()]; + memset( m_outputs[i], 0, bufferSize() * sizeof( float ) ); } #ifdef OLD_VST_SDK if( m_plugin->flags & effFlagsCanReplacing ) { #endif - m_plugin->processReplacing( m_plugin, m_inputs, - m_outputs, - m_blockSize ); + m_plugin->processReplacing( m_plugin, m_inputs, m_outputs, + bufferSize() ); #ifdef OLD_VST_SDK } else { m_plugin->process( m_plugin, m_inputs, m_outputs, - m_blockSize ); + bufferSize() ); } #endif - m_currentSamplePos += m_blockSize; - - writeValue( VST_PROCESS_DONE ); + m_currentSamplePos += bufferSize(); // give plugin some idle-time for GUI-update and so on... m_plugin->dispatcher( m_plugin, effEditIdle, 0, 0, NULL, 0 ); @@ -495,14 +488,14 @@ void VSTPlugin::process( void ) -void VSTPlugin::enqueueMidiEvent( const midiEvent & _event, - const f_cnt_t _frames_ahead ) +void remoteVstPlugin::processMidiEvent( const midiEvent & _event, + const f_cnt_t _offset ) { VstMidiEvent event; event.type = kVstMidiType; event.byteSize = 24; - event.deltaFrames = _frames_ahead; + event.deltaFrames = _offset; event.flags = 0; event.detune = 0; event.noteLength = 0; @@ -530,23 +523,7 @@ void VSTPlugin::enqueueMidiEvent( const midiEvent & _event, -void VSTPlugin::setBlockSize( const fpp_t _bsize ) -{ - if( _bsize == m_blockSize ) - { - return; - } - - m_blockSize = _bsize; - resizeSharedMemory(); - m_plugin->dispatcher( m_plugin, effSetBlockSize, 0, _bsize, NULL, - 0.0f ); -} - - - - -const char * VSTPlugin::pluginName( void ) const +const char * remoteVstPlugin::pluginName( void ) const { static char buf[32]; buf[0] = 0; @@ -558,7 +535,7 @@ const char * VSTPlugin::pluginName( void ) const -const char * VSTPlugin::pluginVendorString( void ) const +const char * remoteVstPlugin::pluginVendorString( void ) const { static char buf[64]; buf[0] = 0; @@ -570,7 +547,7 @@ const char * VSTPlugin::pluginVendorString( void ) const -const char * VSTPlugin::pluginProductString( void ) const +const char * remoteVstPlugin::pluginProductString( void ) const { static char buf[64]; buf[0] = 0; @@ -582,118 +559,100 @@ const char * VSTPlugin::pluginProductString( void ) const -void VSTPlugin::getParameterDump( void ) const +void remoteVstPlugin::getParameterDump( void ) { VstParameterProperties vst_props; - vstParameterDumpItem dump_item; - writeValue( VST_PARAMETER_DUMP ); - writeValue( (Sint32) m_plugin->numParams ); - for( Sint32 i = 0; i < m_plugin->numParams; ++i ) + message m( IdVstParameterDump ); + m.addInt( m_plugin->numParams ); + for( int i = 0; i < m_plugin->numParams; ++i ) { - dump_item.index = i; - m_plugin->dispatcher( m_plugin, effGetParameterProperties, i, 0, - &vst_props, 0.0f ); - memcpy( dump_item.shortLabel, vst_props.shortLabel, - sizeof( dump_item.shortLabel ) ); - dump_item.value = m_plugin->getParameter( m_plugin, i ); - writeValue( dump_item ); + m_plugin->dispatcher( m_plugin, effGetParameterProperties, i, + 0, &vst_props, 0.0f ); + m.addInt( i ); + m.addString( vst_props.shortLabel ); + m.addFloat( m_plugin->getParameter( m_plugin, i ) ); + } + sendMessage( m ); +} + + + + +void remoteVstPlugin::setParameterDump( const message & _m ) +{ + const int n = _m.getInt( 0 ); + const int params = ( n > m_plugin->numParams ) ? + m_plugin->numParams : n; + int p = 0; + for( int i = 0; i < params; ++i ) + { + vstParameterDumpItem item; + item.index = _m.getInt( ++p ); + item.shortLabel = _m.getString( ++p ); + item.value = _m.getFloat( ++p ); + m_plugin->setParameter( m_plugin, item.index, item.value ); } } -void VSTPlugin::setParameterDump( void ) +void remoteVstPlugin::getParameterProperties( const int _idx ) { - const Sint32 sz = readValue(); - const Sint32 params = ( sz > m_plugin->numParams ) ? - m_plugin->numParams : sz; - for( Sint32 i = 0; i < params; ++i ) - { - vstParameterDumpItem dump_item = - readValue(); - m_plugin->setParameter( m_plugin, dump_item.index, - dump_item.value ); - } -} - - - - -void VSTPlugin::getParameterProperties( const Sint32 _idx ) -{ - VstParameterProperties vst_props; + VstParameterProperties p; m_plugin->dispatcher( m_plugin, effGetParameterProperties, _idx, 0, - &vst_props, 0.0f ); - vstParamProperties props; - memcpy( props.label, vst_props.label, sizeof( props.label ) ); - memcpy( props.shortLabel, vst_props.shortLabel, - sizeof( props.shortLabel) ); + &p, 0.0f ); + message m( IdVstParameterProperties ); + m.addString( p.label ); + m.addString( p.shortLabel ); + m.addString( #if kVstVersion > 2 - memcpy( props.categoryLabel, vst_props.categoryLabel, - sizeof( props.categoryLabel ) ); + p.categoryLabel +#else + "" #endif - props.minValue = vst_props.minInteger; - props.maxValue = vst_props.maxInteger; - props.step = ( vst_props.flags & kVstParameterUsesFloatStep ) ? - vst_props.stepFloat : - vst_props.stepInteger; + ); + m.addFloat( p.minInteger ); + m.addFloat( p.maxInteger ); + m.addFloat( ( p.flags & kVstParameterUsesFloatStep ) ? + p.stepFloat : p.stepInteger ); + m.addInt( #if kVstVersion > 2 - props.category = vst_props.category; + p.category +#else + 0 #endif - writeValue( VST_PARAMETER_PROPERTIES ); - writeValue( props ); + ); + sendMessage( m ); } -void VSTPlugin::resizeSharedMemory( void ) +void remoteVstPlugin::updateInOutCount( void ) { delete[] m_inputs; delete[] m_outputs; - size_t s = ( inputCount() + outputCount() ) * m_blockSize * - sizeof( float ); - if( m_shm != NULL ) - { - shmdt( m_shm ); - } - - int shm_id; - Uint16 shm_key = 0; - while( ( shm_id = shmget( ++shm_key, s, IPC_CREAT | IPC_EXCL | - 0600 ) ) == -1 ) - { - } - - m_shm = (float *) shmat( shm_id, 0, 0 ); + setInputCount( inputCount() ); + setOutputCount( outputCount() ); if( inputCount() > 0 ) { m_inputs = new float * [inputCount()]; } + if( outputCount() > 0 ) { m_outputs = new float * [outputCount()]; } - - writeValue( VST_INPUT_COUNT ); - writeValue( inputCount() ); - - writeValue( VST_OUTPUT_COUNT ); - writeValue( outputCount() ); - - writeValue( VST_SHM_KEY_AND_SIZE ); - writeValue( shm_key ); - writeValue( s ); } #define DEBUG_CALLBACKS #ifdef DEBUG_CALLBACKS -#define SHOW_CALLBACK lvsMessage +#define SHOW_CALLBACK printf #else #define SHOW_CALLBACK(...) #endif @@ -706,7 +665,7 @@ void VSTPlugin::resizeSharedMemory( void ) * - audioMasterGetDirectory: return either VST-plugin-dir or LMMS-workingdir * - audioMasterOpenFileSelector: show QFileDialog? */ -VstIntPtr VSTPlugin::hostCallback( AEffect * _effect, VstInt32 _opcode, +VstIntPtr remoteVstPlugin::hostCallback( AEffect * _effect, VstInt32 _opcode, VstInt32 _index, VstIntPtr _value, void * _ptr, float _opt ) { @@ -756,10 +715,10 @@ VstIntPtr VSTPlugin::hostCallback( AEffect * _effect, VstInt32 _opcode, memset( &_timeInfo, 0, sizeof( _timeInfo ) ); - _timeInfo.samplePos = plugin->m_currentSamplePos; - _timeInfo.sampleRate = plugin->m_sampleRate; + _timeInfo.samplePos = __plugin->m_currentSamplePos; + _timeInfo.sampleRate = __plugin->sampleRate(); _timeInfo.flags = 0; - _timeInfo.tempo = plugin->m_bpm; + _timeInfo.tempo = __plugin->m_bpm; _timeInfo.timeSigNumerator = 4; _timeInfo.timeSigDenominator = 4; _timeInfo.flags |= (/* kVstBarsValid|*/kVstTempoValid ); @@ -773,7 +732,7 @@ VstIntPtr VSTPlugin::hostCallback( AEffect * _effect, VstInt32 _opcode, return( 0 ); case audioMasterIOChanged: - plugin->resizeSharedMemory(); + __plugin->updateInOutCount(); //SHOW_CALLBACK( "amc: audioMasterIOChanged\n" ); // numInputs and/or numOutputs has changed return( 0 ); @@ -792,7 +751,7 @@ VstIntPtr VSTPlugin::hostCallback( AEffect * _effect, VstInt32 _opcode, case audioMasterTempoAt: //SHOW_CALLBACK( "amc: audioMasterTempoAt\n" ); - return( plugin->m_bpm * 10000 ); + return( __plugin->m_bpm * 10000 ); case audioMasterGetNumAutomatableParameters: SHOW_CALLBACK( "amc: audioMasterGetNumAutomatable" @@ -864,36 +823,37 @@ VstIntPtr VSTPlugin::hostCallback( AEffect * _effect, VstInt32 _opcode, case audioMasterSizeWindow: //SHOW_CALLBACK( "amc: audioMasterSizeWindow\n" ); - if( plugin->m_window == 0 ) + if( __plugin->m_window == 0 ) { return( 0 ); } - plugin->m_windowWidth = _index; - plugin->m_windowHeight = _value; - SetWindowPos( plugin->m_window, 0, 0, 0, + __plugin->m_windowWidth = _index; + __plugin->m_windowHeight = _value; + SetWindowPos( __plugin->m_window, 0, 0, 0, _index + 8, _value + 26, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER ); - writeValue( VST_PLUGIN_EDITOR_GEOMETRY ); - writeValue( plugin->m_windowWidth ); - writeValue( plugin->m_windowHeight ); + __plugin->sendMessage( + message( IdVstPluginEditorGeometry ). + addInt( __plugin->m_windowWidth ). + addInt( __plugin->m_windowHeight ) ); return( 1 ); case audioMasterGetSampleRate: //SHOW_CALLBACK( "amc: audioMasterGetSampleRate\n" ); - return( plugin->m_sampleRate ); + return( __plugin->sampleRate() ); case audioMasterGetBlockSize: //SHOW_CALLBACK( "amc: audioMasterGetBlockSize\n" ); - return( plugin->m_blockSize ); + return( __plugin->bufferSize() ); case audioMasterGetInputLatency: //SHOW_CALLBACK( "amc: audioMasterGetInputLatency\n" ); - return( plugin->m_blockSize ); + return( __plugin->bufferSize() ); case audioMasterGetOutputLatency: //SHOW_CALLBACK( "amc: audioMasterGetOutputLatency\n" ); - return( plugin->m_blockSize ); + return( __plugin->bufferSize() ); case audioMasterGetCurrentProcessLevel: SHOW_CALLBACK( "amc: audioMasterGetCurrentProcess" @@ -1019,16 +979,16 @@ VstIntPtr VSTPlugin::hostCallback( AEffect * _effect, VstInt32 _opcode, -DWORD WINAPI VSTPlugin::guiEventLoop( LPVOID _param ) +DWORD WINAPI remoteVstPlugin::guiEventLoop( LPVOID _param ) { - VSTPlugin * _this = static_cast( _param ); + remoteVstPlugin * _this = static_cast( _param ); _this->m_guiThreadID = GetCurrentThreadId(); // "guard point" to trap errors that occur during plugin loading #ifdef LMMS_HAVE_TLS if( sigsetjmp( ejmpbuf, 1 ) ) { - lvsMessage( "creating the editor for %s failed", + fprintf( stderr, "creating the editor for %s failed\n", _this->m_shortName.c_str() ); pthread_cond_signal( &_this->m_windowStatusChange ); return( 1 ); @@ -1064,7 +1024,7 @@ DWORD WINAPI VSTPlugin::guiEventLoop( LPVOID _param ) HMODULE hInst = GetModuleHandleA( NULL ); if( hInst == NULL ) { - lvsMessage( "can't get module handle" ); + fprintf( stderr, "can't get module handle\n" ); pthread_cond_signal( &_this->m_windowStatusChange ); return( 1 ); } @@ -1075,14 +1035,14 @@ DWORD WINAPI VSTPlugin::guiEventLoop( LPVOID _param ) ~WS_MAXIMIZEBOX ), 0, 0, 1, 1, NULL, NULL, hInst, NULL ) ) == NULL ) { - lvsMessage( "cannot create editor window" ); + fprintf( stderr, "cannot create editor window\n" ); pthread_cond_signal( &_this->m_windowStatusChange ); return( 1 ); } ShowWindow( _this->m_window, SW_SHOWMINIMIZED ); ShowWindow( _this->m_window, SW_HIDE ); - _this->m_windowXID = (Sint32) GetPropA( _this->m_window, + _this->m_windowID = (Sint32) GetPropA( _this->m_window, "__wine_x11_whole_window" ); @@ -1148,13 +1108,25 @@ DWORD WINAPI VSTPlugin::guiEventLoop( LPVOID _param ) -int main( void ) +int main( int _argc, char * * _argv ) { + if( _argc < 3 ) + { + fprintf( stderr, "not enough arguments\n" ); + return( -1 ); + } + +#ifdef LMMS_BUILD_WIN32 + // (non-portable) initialization of statically linked pthread library + pthread_win32_process_attach_np(); + pthread_win32_thread_attach_np(); +#endif + // WINE-startup HMODULE hInst = GetModuleHandleA( NULL ); if( hInst == NULL ) { - lvsMessage( "can't get module handle" ); + fprintf( stderr, "can't get module handle\n" ); return( -1 ); } @@ -1182,84 +1154,28 @@ int main( void ) sched_get_priority_min( SCHED_FIFO ) ) / 2; if( sched_setscheduler( 0, SCHED_FIFO, &sparam ) == -1 ) { - lvsMessage( "could not set realtime priority for VST-server" ); + fprintf( stderr, "could not set realtime priority for " + "remoteVstPlugin\n" ); } #endif - Sint16 cmd; - while( ( cmd = readValue() ) != VST_CLOSE_PLUGIN ) - { - switch( cmd ) - { - case VST_LOAD_PLUGIN: - plugin = new VSTPlugin(); - plugin->init( readString() ); - break; + __plugin = new remoteVstPlugin( atoi( _argv[1] ), atoi( _argv[2] ) ); - case VST_SHOW_EDITOR: - plugin->showEditor(); - break; - - case VST_PROCESS: - plugin->process(); - break; - - case VST_ENQUEUE_MIDI_EVENT: - { - MidiEventTypes type = - readValue(); - Sint8 channel = readValue(); - Uint16 param1 = readValue(); - Uint16 param2 = readValue(); - const midiEvent ev = midiEvent( type, channel, - param1, param2 ); - - const f_cnt_t fr_ahead = readValue(); - plugin->enqueueMidiEvent( ev, fr_ahead ); - break; - } - - case VST_SAMPLE_RATE: - plugin->setSampleRate( - readValue() ); - break; - - - case VST_BUFFER_SIZE: - plugin->setBlockSize( readValue() ); - break; - - case VST_BPM: - plugin->setBPM( readValue() ); - break; - - case VST_LANGUAGE: - hlang = readValue(); - break; - - case VST_GET_PARAMETER_DUMP: - plugin->getParameterDump(); - break; - - case VST_SET_PARAMETER_DUMP: - plugin->setParameterDump(); - break; - - case VST_GET_PARAMETER_PROPERTIES: - plugin->getParameterProperties( - readValue() ); - break; - - default: - lvsMessage( "unhandled message: %d\n", - (int) cmd ); - break; - } + remotePluginClient::message m; + while( ( m = __plugin->receiveMessage() ).id != IdQuit ) + { + __plugin->processMessage( m ); } - delete plugin; + delete __plugin; - return( 0 ); + +#ifdef LMMS_BUILD_WIN32 + pthread_win32_thread_detach_np(); + pthread_win32_process_detach_np(); +#endif + + return 0; } diff --git a/plugins/vst_base/vst_plugin.cpp b/plugins/vst_base/vst_plugin.cpp index b98c48bd6..85a7c0a84 100644 --- a/plugins/vst_base/vst_plugin.cpp +++ b/plugins/vst_base/vst_plugin.cpp @@ -1,5 +1,5 @@ /* - * lvsl_client.cpp - client for LVSL Server + * vst_plugin.cpp - implementation of vstPlugin class * * Copyright (c) 2005-2008 Tobias Doerffel * @@ -23,50 +23,17 @@ */ -#include "lvsl_client.h" -#include "lmmsconfig.h" +#include "vst_plugin.h" -#include #include -#include +#include #include -#include #include #include #include #include #include -#ifdef LMMS_HAVE_UNISTD_H -#include -#endif - -#ifdef LMMS_HAVE_SIGNAL_H -#include -#endif - -#include - -#ifdef LMMS_HAVE_SYS_IPC_H -#include -#endif - -#ifdef LMMS_HAVE_SYS_SHM_H -#include -#endif - -#ifdef LMMS_HAVE_SYS_SELECT_H -#include -#endif - -#ifdef LMMS_HAVE_SYS_TIME_H -#include -#endif - -#ifdef LMMS_HAVE_SYS_WAIT_H -#include -#endif - #include "config_mgr.h" #include "engine.h" @@ -76,54 +43,23 @@ -remoteVSTPlugin::remoteVSTPlugin( const QString & _plugin ) : +vstPlugin::vstPlugin( const QString & _plugin ) : QObject(), - m_failed( TRUE ), + journallingObject(), + remotePlugin( "remote_vst_plugin", false ), m_plugin( _plugin ), m_pluginWidget( NULL ), - m_pluginXID( 0 ), - m_pluginPID( -1 ), - m_serverInFD( -1 ), - m_serverOutFD( -1 ), - m_serverMutex(), + m_pluginWindowID( 0 ), m_name( "" ), m_version( 0 ), m_vendorString( "" ), - m_productString( "" ), - m_inputCount( 0 ), - m_outputCount( 0 ), - m_shmID( -1 ), - m_shm( NULL ), - m_shmSize( 0 ), - m_initialized( FALSE ) + m_productString( "" ) { - pipe( m_pipes[0] ); - pipe( m_pipes[1] ); - - if( ( m_pluginPID = fork() ) < 0 ) - { - printf( "fork() failed!\n" ); - return; - } - else if( m_pluginPID == 0 ) - { - dup2( m_pipes[0][0], 0 ); - dup2( m_pipes[1][1], 1 ); - QString lvsl_server_exec = configManager::inst()->pluginDir() + - QDir::separator() + - "lvsl_server"; - execlp( lvsl_server_exec.toAscii().constData(), - lvsl_server_exec.toAscii().constData(), - NULL ); - exit( 0 ); - } - m_serverInFD = m_pipes[1][0]; - m_serverOutFD = m_pipes[0][1]; + setSplittedChannels( true ); lock(); - writeValueS( VST_LANGUAGE ); - hostLanguages hlang = LanguageEnglish; + VstHostLanguages hlang = LanguageEnglish; switch( QLocale::system().language() ) { case QLocale::German: hlang = LanguageGerman; break; @@ -133,7 +69,8 @@ remoteVSTPlugin::remoteVSTPlugin( const QString & _plugin ) : case QLocale::Japanese: hlang = LanguageJapanese; break; default: break; } - writeValueS( hlang ); + sendMessage( message( IdVstSetLanguage ).addInt( hlang ) ); + QString p = m_plugin; if( QFileInfo( p ).dir().isRelative() ) @@ -141,81 +78,31 @@ remoteVSTPlugin::remoteVSTPlugin( const QString & _plugin ) : p = configManager::inst()->vstDir() + QDir::separator() + p; } - writeValueS( VST_LOAD_PLUGIN ); - writeStringS( p.toAscii().constData() ); + sendMessage( message( IdVstLoadPlugin ).addString( p.toStdString() ) ); + + waitForInitDone(); + unlock(); - - while( 1 ) - { - Sint16 cmd = VST_UNDEFINED_CMD; - if( messagesLeft() == TRUE ) - { - cmd = processNextMessage(); - } - if( cmd == VST_INITIALIZATION_DONE ) - { - m_failed = FALSE; - break; - } - else if( cmd == VST_FAILED_LOADING_PLUGIN ) - { - break; - } - QCoreApplication::processEvents( QEventLoop::AllEvents, 50 ); - } } -remoteVSTPlugin::~remoteVSTPlugin() +vstPlugin::~vstPlugin() { - if( m_failed == FALSE ) + if( m_pluginWidget != NULL && + m_pluginWidget->parentWidget() != NULL && + dynamic_cast( + m_pluginWidget->parentWidget() ) != NULL ) { - setShmKeyAndSize( 0, 0 ); - // tell server to quit and wait for acknowledge - writeValueS( VST_CLOSE_PLUGIN ); - QTime t; - t.start(); - while( t.elapsed() < 1000 ) - { - if( messagesLeft() == TRUE && - processNextMessage() == VST_QUIT_ACK ) - { - //m_pluginPID = 0; - break; - } - } - if( m_pluginWidget != NULL && - m_pluginWidget->parentWidget() != NULL && - dynamic_cast( - m_pluginWidget->parentWidget() ) != NULL ) - { - delete m_pluginWidget->parentWidget(); - } - // timeout? -/* if( m_pluginPID != 0 ) - {*/ - kill( m_pluginPID, SIGTERM ); - kill( m_pluginPID, SIGKILL ); - //} - // remove process from PCB - waitpid( m_pluginPID, NULL, 0 ); - - // close all sides of our pipes - close( m_pipes[0][0] ); - close( m_pipes[0][1] ); - close( m_pipes[1][0] ); - close( m_pipes[1][1] ); -/* close( m_serverInFD ); - close( m_serverOutFD );*/ + delete m_pluginWidget->parentWidget(); } } -QWidget * remoteVSTPlugin::showEditor( QWidget * _parent ) +QWidget * vstPlugin::showEditor( QWidget * _parent ) { if( m_pluginWidget != NULL ) { @@ -226,7 +113,7 @@ QWidget * remoteVSTPlugin::showEditor( QWidget * _parent ) return( m_pluginWidget ); } - if( m_pluginXID == 0 ) + if( m_pluginWindowID == 0 ) { return( NULL ); } @@ -236,20 +123,22 @@ QWidget * remoteVSTPlugin::showEditor( QWidget * _parent ) m_pluginWidget->setWindowTitle( name() ); if( _parent == NULL ) { - engine::getMainWindow()->workspace()->addSubWindow( m_pluginWidget ) + engine::getMainWindow()->workspace()->addSubWindow( + m_pluginWidget ) ->setAttribute( Qt::WA_DeleteOnClose, FALSE ); } +#ifdef LMMS_BUILD_LINUX QX11EmbedContainer * xe = new QX11EmbedContainer( m_pluginWidget ); - xe->embedClient( m_pluginXID ); + xe->embedClient( m_pluginWindowID ); xe->setFixedSize( m_pluginGeometry ); //xe->setAutoDelete( FALSE ); xe->show(); +#endif + m_pluginWidget->show(); - lock(); - writeValueS( VST_SHOW_EDITOR ); - unlock(); + showUI(); return( m_pluginWidget ); } @@ -257,7 +146,7 @@ QWidget * remoteVSTPlugin::showEditor( QWidget * _parent ) -void remoteVSTPlugin::hideEditor( void ) +void vstPlugin::hideEditor( void ) { if( m_pluginWidget != NULL && m_pluginWidget->parentWidget() ) { @@ -268,116 +157,7 @@ void remoteVSTPlugin::hideEditor( void ) -bool remoteVSTPlugin::process( const sampleFrame * _in_buf, - sampleFrame * _out_buf, bool _wait ) -{ - const fpp_t frames = engine::getMixer()->framesPerPeriod(); - - if( m_shm == NULL ) - { - // m_shm being zero means we didn't initialize everything so - // far so process one message each time (and hope we get - // information like SHM-key etc.) until we process messages - // in a later stage of this procedure - if( m_shmSize == 0 && messagesLeft() == TRUE ) - { - (void) processNextMessage(); - } - if( _out_buf != NULL ) - { - engine::getMixer()->clearAudioBuffer( _out_buf, - frames ); - } - return( FALSE ); - } - - memset( m_shm, 0, m_shmSize ); - - ch_cnt_t inputs = tMax( m_inputCount, DEFAULT_CHANNELS ); - - if( _in_buf != NULL && inputs > 0 ) - { - for( ch_cnt_t ch = 0; ch < inputs; ++ch ) - { - for( fpp_t frame = 0; frame < frames; ++frame ) - { - m_shm[ch * frames + frame] = _in_buf[frame][ch]; - } - } - } - - lock(); - writeValueS( VST_PROCESS ); - unlock(); - - m_initialized = TRUE; - if( _wait ) - { - waitForProcessingFinished( _out_buf ); - } - return( TRUE ); -} - - - - -bool remoteVSTPlugin::waitForProcessingFinished( sampleFrame * _out_buf ) -{ - if( !m_initialized || _out_buf == NULL || m_outputCount == 0 ) - { - return( FALSE ); - } - - // wait until server signals that process()ing is done - while( processNextMessage() != VST_PROCESS_DONE ) - { - // hopefully scheduler gives process-time to plugin... - usleep( 10 ); - } - - const fpp_t frames = engine::getMixer()->framesPerPeriod(); - const ch_cnt_t outputs = tMax( m_outputCount, - DEFAULT_CHANNELS ); - if( outputs != DEFAULT_CHANNELS ) - { - // clear buffer, if plugin didn't fill up both channels - engine::getMixer()->clearAudioBuffer( _out_buf, frames ); - } - - for( ch_cnt_t ch = 0; ch < outputs; ++ch ) - { - for( fpp_t frame = 0; frame < frames; ++frame ) - { - _out_buf[frame][ch] = m_shm[( m_inputCount + ch ) * - frames + frame]; - } - } - - return( TRUE ); -} - - - - -void remoteVSTPlugin::enqueueMidiEvent( const midiEvent & _event, - const f_cnt_t _frames_ahead ) -{ - lock(); - writeValueS( VST_ENQUEUE_MIDI_EVENT ); - - writeValueS( _event.m_type ); - writeValueS( _event.m_channel ); - writeValueS( _event.m_data.m_param[0] ); - writeValueS( _event.m_data.m_param[1] ); - - writeValueS( _frames_ahead ); - unlock(); -} - - - - -void remoteVSTPlugin::loadSettings( const QDomElement & _this ) +void vstPlugin::loadSettings( const QDomElement & _this ) { if( pluginWidget() != NULL ) { @@ -407,7 +187,7 @@ void remoteVSTPlugin::loadSettings( const QDomElement & _this ) -void remoteVSTPlugin::saveSettings( QDomDocument & _doc, QDomElement & _this ) +void vstPlugin::saveSettings( QDomDocument & _doc, QDomElement & _this ) { if( pluginWidget() != NULL ) { @@ -425,36 +205,31 @@ void remoteVSTPlugin::saveSettings( QDomDocument & _doc, QDomElement & _this ) -void remoteVSTPlugin::setTempo( bpm_t _bpm ) +void vstPlugin::setTempo( bpm_t _bpm ) { lock(); - writeValueS( VST_BPM ); - writeValueS( _bpm ); + sendMessage( message( IdVstSetTempo ).addInt( _bpm ) ); unlock(); } -void remoteVSTPlugin::updateSampleRate( void ) +void vstPlugin::updateSampleRate( void ) { lock(); - writeValueS( VST_SAMPLE_RATE ); - writeValueS( - engine::getMixer()->processingSampleRate() ); + sendMessage( message( IdSampleRateInformation ). + addInt( engine::getMixer()->processingSampleRate() ) ); unlock(); } -const QMap & remoteVSTPlugin::parameterDump( void ) +const QMap & vstPlugin::parameterDump( void ) { - writeValueS( VST_GET_PARAMETER_DUMP ); - - while( processNextMessage() != VST_PARAMETER_DUMP ) - { - } + sendMessage( IdVstGetParameterDump ); + waitForMessage( IdVstParameterDump ); return( m_parameterDump ); } @@ -462,127 +237,43 @@ const QMap & remoteVSTPlugin::parameterDump( void ) -void remoteVSTPlugin::setParameterDump( const QMap & _pdump ) +void vstPlugin::setParameterDump( const QMap & _pdump ) { - writeValueS( VST_SET_PARAMETER_DUMP ); - writeValueS( _pdump.size() ); + message m( IdVstSetParameterDump ); + m.addInt( _pdump.size() ); for( QMap::const_iterator it = _pdump.begin(); it != _pdump.end(); ++it ) { - const vstParameterDumpItem dump_item = + const vstParameterDumpItem item = { ( *it ).section( ':', 0, 0 ).toInt(), "", ( *it ).section( ':', 1, 1 ).toFloat() } ; - writeValueS( dump_item ); + m.addInt( item.index ); + m.addString( item.shortLabel ); + m.addFloat( item.value ); } -} - - - - -void remoteVSTPlugin::setShmKeyAndSize( Uint16 _key, size_t _size ) -{ - if( m_shm != NULL && m_shmSize > 0 ) - { - shmdt( m_shm ); - m_shm = NULL; - m_shmSize = 0; - } - - // only called for detaching SHM? - if( _size == 0 ) - { - return; - } - - int shm_id = shmget( _key, _size, 0 ); - if( shm_id == -1 ) - { - printf( "failed getting shared memory\n" ); - } - else - { - m_shm = (float *) shmat( shm_id, 0, 0 ); - // TODO: error-checking - } -} - - - - -bool remoteVSTPlugin::messagesLeft( void ) const -{ - fd_set rfds; - FD_ZERO( &rfds ); - FD_SET( m_serverInFD, &rfds ); - timeval tv; - tv.tv_sec = 0; - tv.tv_usec = 1; // can we use 0 here? - return( select( m_serverInFD + 1, &rfds, NULL, NULL, &tv ) > 0 ); -} - - - - -Sint16 remoteVSTPlugin::processNextMessage( void ) -{ - fd_set rfds; - FD_ZERO( &rfds ); - FD_SET( m_serverInFD, &rfds ); - if( select( m_serverInFD + 1, &rfds, NULL, NULL, NULL ) <= 0 ) - { - return( VST_UNDEFINED_CMD ); - } - lock(); - Sint16 cmd = readValueS(); - switch( cmd ) + sendMessage( m ); + unlock(); +} + + + + +bool vstPlugin::processMessage( const message & _m ) +{ + switch( _m.id ) { - case VST_DEBUG_MSG: - printf( "debug message from server: %s\n", - readStringS().c_str() ); + case IdVstPluginWindowID: + m_pluginWindowID = _m.getInt(); break; - case VST_GET_SAMPLE_RATE: - writeValueS( VST_SAMPLE_RATE ); - // handle is the same - writeValueS( - engine::getMixer()->processingSampleRate() ); - break; - - case VST_GET_BUFFER_SIZE: - writeValueS( VST_BUFFER_SIZE ); - // handle is the same - writeValueS( - engine::getMixer()->framesPerPeriod() ); - break; - - case VST_SHM_KEY_AND_SIZE: + case IdVstPluginEditorGeometry: { - Uint16 shm_key = readValueS(); - size_t shm_size = readValueS(); - setShmKeyAndSize( shm_key, shm_size ); - break; - } - - case VST_INPUT_COUNT: - m_inputCount = readValueS(); - break; - - case VST_OUTPUT_COUNT: - m_outputCount = readValueS(); - break; - - case VST_PLUGIN_XID: - m_pluginXID = readValueS(); - break; - - case VST_PLUGIN_EDITOR_GEOMETRY: - { - const Sint16 w = readValueS(); - const Sint16 h = readValueS(); + const int w = _m.getInt( 0 ); + const int h = _m.getInt( 1 ); m_pluginGeometry = QSize( w, h ); if( m_pluginWidget != NULL ) { @@ -598,50 +289,48 @@ Sint16 remoteVSTPlugin::processNextMessage( void ) break; } - case VST_PLUGIN_NAME: - m_name = readStringS().c_str(); + case IdVstPluginName: + m_name = _m.getQString(); break; - case VST_PLUGIN_VERSION: - m_version = readValueS(); + case IdVstPluginVersion: + m_version = _m.getInt(); break; - case VST_PLUGIN_VENDOR_STRING: - m_vendorString = readStringS().c_str(); + case IdVstPluginVendorString: + m_vendorString = _m.getQString(); break; - case VST_PLUGIN_PRODUCT_STRING: - m_productString = readStringS().c_str(); + case IdVstPluginProductString: + m_productString = _m.getQString(); break; - case VST_PARAMETER_DUMP: + case IdVstParameterDump: { m_parameterDump.clear(); - const Sint32 num_params = readValueS(); - for( Sint32 i = 0; i < num_params; ++i ) + const int num_params = _m.getInt(); + int p = 0; + for( int i = 0; i < num_params; ++i ) { - vstParameterDumpItem dump_item = - readValueS(); - m_parameterDump["param" + QString::number( dump_item.index )] = - QString::number( dump_item.index ) + ":" + -// QString( dump_item.shortLabel ) + ":" + - QString::number( dump_item.value ); + vstParameterDumpItem item; + item.index = _m.getInt( ++p ); + item.shortLabel = _m.getString( ++p ); + item.value = _m.getFloat( ++p ); + m_parameterDump["param" + QString::number( item.index )] = + QString::number( item.index ) + ":" + +// QString( item.shortLabel ) + ":" + + QString::number( item.value ); } break; } - - case VST_PROCESS_DONE: - case VST_QUIT_ACK: - case VST_UNDEFINED_CMD: default: - break; + return remotePlugin::processMessage( _m ); } - unlock(); + return true; - return( cmd ); } -#include "moc_lvsl_client.cxx" +#include "moc_vst_plugin.cxx" diff --git a/plugins/vst_base/vst_plugin.h b/plugins/vst_base/vst_plugin.h index 7ec34e31d..f87d749c4 100644 --- a/plugins/vst_base/vst_plugin.h +++ b/plugins/vst_base/vst_plugin.h @@ -1,5 +1,5 @@ /* - * lvsl_client.h - client for LVSL Server + * vst_plugin.h - declaration of vstPlugin class * * Copyright (c) 2005-2008 Tobias Doerffel * @@ -23,26 +23,28 @@ */ -#ifndef _LVSL_CLIENT_H -#define _LVSL_CLIENT_H +#ifndef _VST_PLUGIN_H +#define _VST_PLUGIN_H #include #include #include #include "mixer.h" -#include "communication.h" -#include "midi.h" #include "journalling_object.h" +#include "communication.h" +#include "remote_plugin.h" -class remoteVSTPlugin : public QObject, public journallingObject +class vstPlugin : public QObject, public journallingObject, public remotePlugin { Q_OBJECT public: - remoteVSTPlugin( const QString & _plugin ); - virtual ~remoteVSTPlugin(); + vstPlugin( const QString & _plugin ); + virtual ~vstPlugin(); + + virtual bool processMessage( const message & _m ); QWidget * showEditor( QWidget * _parent = NULL ); void hideEditor( void ); @@ -67,42 +69,16 @@ public: return( m_productString ); } - // if _wait == TRUE, process() calls waitForProcessingFinished() - // immediately, otherwise, _out_buf can be zero and you've to call - // waitForProcessingFinished() on your own - bool process( const sampleFrame * _in_buf, sampleFrame * _out_buf, - bool _wait ); - bool waitForProcessingFinished( sampleFrame * _out_buf ); - - - void enqueueMidiEvent( const midiEvent & _event, - const f_cnt_t _frames_ahead ); - const QMap & parameterDump( void ); void setParameterDump( const QMap & _pdump ); - inline Uint8 inputCount( void ) const - { - return( m_inputCount ); - } - - inline Uint8 outputCount( void ) const - { - return( m_outputCount ); - } - inline QWidget * pluginWidget( void ) { return( m_pluginWidget != NULL ? m_pluginWidget->parentWidget() : NULL ); } - inline bool failed( void ) const - { - return( m_failed ); - } - virtual void loadSettings( const QDomElement & _this ); virtual void saveSettings( QDomDocument & _doc, QDomElement & _this ); @@ -118,57 +94,11 @@ public slots: private: - template - inline T readValueS( void ) const - { - return( ::readValue( m_serverInFD ) ); - } - - template - inline void writeValueS( const T & _i ) const - { - ::writeValue( _i, m_serverOutFD ); - } - - inline std::string readStringS( void ) const - { - return( ::readString( m_serverInFD ) ); - } - - inline void writeStringS( const char * _str ) const - { - ::writeString( _str, m_serverOutFD ); - } - - inline void lock( void ) - { - m_serverMutex.lock(); - } - - inline void unlock( void ) - { - m_serverMutex.unlock(); - } - - bool messagesLeft( void ) const; - Sint16 processNextMessage( void ); - - void setShmKeyAndSize( const Uint16 _key, const size_t _size ); - - - bool m_failed; QString m_plugin; QWidget * m_pluginWidget; - Sint32 m_pluginXID; + int m_pluginWindowID; QSize m_pluginGeometry; - int m_pluginPID; - int m_pipes[2][2]; - int m_serverInFD; - int m_serverOutFD; - - QMutex m_serverMutex; - QString m_name; Sint32 m_version; QString m_vendorString; @@ -176,15 +106,6 @@ private: QMap m_parameterDump; - Uint8 m_inputCount; - Uint8 m_outputCount; - - int m_shmID; - float * m_shm; - size_t m_shmSize; - - bool m_initialized; - } ; diff --git a/plugins/vst_effect/vst_effect.cpp b/plugins/vst_effect/vst_effect.cpp index 26d1d99ef..8c6330fc3 100644 --- a/plugins/vst_effect/vst_effect.cpp +++ b/plugins/vst_effect/vst_effect.cpp @@ -125,20 +125,20 @@ bool vstEffect::processAudioBuffer( sampleFrame * _buf, const fpp_t _frames ) void vstEffect::openPlugin( const QString & _plugin ) { textFloat * tf = textFloat::displayMessage( - remoteVSTPlugin::tr( "Loading plugin" ), - remoteVSTPlugin::tr( + vstPlugin::tr( "Loading plugin" ), + vstPlugin::tr( "Please wait while loading VST-plugin..." ), PLUGIN_NAME::getIconPixmap( "logo", 24, 24 ), 0 ); m_pluginMutex.lock(); - m_plugin = new remoteVSTPlugin( _plugin ); + m_plugin = new vstPlugin( _plugin ); if( m_plugin->failed() ) { m_pluginMutex.unlock(); closePlugin(); delete tf; QMessageBox::information( NULL, - remoteVSTPlugin::tr( "Failed loading VST-plugin" ), - remoteVSTPlugin::tr( "The VST-plugin %1 could not " + vstPlugin::tr( "Failed loading VST-plugin" ), + vstPlugin::tr( "The VST-plugin %1 could not " "be loaded for some reason.\n" "If it runs with other VST-" "software under Linux, please " @@ -147,7 +147,7 @@ void vstEffect::openPlugin( const QString & _plugin ) QMessageBox::Ok ); return; } - remoteVSTPlugin::connect( engine::getSong(), + vstPlugin::connect( engine::getSong(), SIGNAL( tempoChanged( bpm_t ) ), m_plugin, SLOT( setTempo( bpm_t ) ) ); m_plugin->setTempo( engine::getSong()->getTempo() ); diff --git a/plugins/vst_effect/vst_effect.h b/plugins/vst_effect/vst_effect.h index 97181d943..10734759a 100644 --- a/plugins/vst_effect/vst_effect.h +++ b/plugins/vst_effect/vst_effect.h @@ -29,7 +29,7 @@ #include #include "effect.h" -#include "lvsl_client.h" +#include "vst_plugin.h" #include "vst_effect_control_dialog.h" #include "vst_effect_controls.h" @@ -61,7 +61,7 @@ private: void openPlugin( const QString & _plugin ); void closePlugin( void ); - remoteVSTPlugin * m_plugin; + vstPlugin * m_plugin; QMutex m_pluginMutex; effectKey m_key;