From 014ecfa901b6d75f88505ed0022767becdf7e42e Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Wed, 3 Sep 2008 16:04:56 +0000 Subject: [PATCH] * added channel splitting mode * made initial wait optional * messages now can be constructed and set inline git-svn-id: https://lmms.svn.sf.net/svnroot/lmms/trunk/lmms@1541 0778d3d1-df1d-0410-868b-ea421aaaa00d --- include/remote_plugin.h | 135 +++++++++++++++++++++++++++++-------- src/core/remote_plugin.cpp | 81 +++++++++++++++------- 2 files changed, 165 insertions(+), 51 deletions(-) diff --git a/include/remote_plugin.h b/include/remote_plugin.h index 665eb7090..bf5a9933f 100755 --- a/include/remote_plugin.h +++ b/include/remote_plugin.h @@ -26,11 +26,11 @@ #ifndef _REMOTE_PLUGIN_H #define _REMOTE_PLUGIN_H -#include "lmmsconfig.h" -#include "mixer.h" +#include "export.h" #include "midi.h" #include +#include #include #include @@ -74,6 +74,7 @@ typedef int32_t key_t; #define EXPORT #define COMPILE_REMOTE_PLUGIN_BASE #else +#include #include #endif @@ -428,7 +429,7 @@ enum RemoteMessageIDs IdUndefined, IdGeneralFailure, IdInitDone, - IdClosePlugin, + IdQuit, IdSampleRateInformation, IdBufferSizeInformation, IdMidiEvent, @@ -472,26 +473,64 @@ public: { } - void addInt( int _i ) + inline message & addString( const std::string & _s ) + { + data.push_back( _s ); + return( *this ); + } + + message & addInt( int _i ) { char buf[128]; buf[0] = 0; sprintf( buf, "%d", _i ); data.push_back( std::string( buf ) ); + return( *this ); } - int getInt( int _p ) const + message & addFloat( float _f ) + { + char buf[128]; + buf[0] = 0; + sprintf( buf, "%f", _f ); + data.push_back( std::string( buf ) ); + return( *this ); + } + + inline std::string getString( int _p = 0 ) const + { + return( data[_p] ); + } + +#ifndef BUILD_REMOTE_PLUGIN_CLIENT + inline QString getQString( int _p = 0 ) const + { + return( QString::fromStdString( getString( _p ) ) ); + } +#endif + + inline int getInt( int _p = 0 ) const { return( atoi( data[_p].c_str() ) ); } - bool operator==( const message & _m ) + inline float getFloat( int _p ) const + { + return( atof( data[_p].c_str() ) ); + } + + inline bool operator==( const message & _m ) const { return( id == _m.id ); } int id; + + private: std::vector data; + + friend class remotePluginBase; + } ; remotePluginBase( shmFifo * _in, shmFifo * _out ); @@ -507,7 +546,7 @@ public: message waitForMessage( const message & _m, - bool _busy_waiting = FALSE ); + bool _busy_waiting = false ); inline message fetchAndProcessNextMessage( void ) { @@ -552,9 +591,15 @@ private: class EXPORT remotePlugin : public remotePluginBase { public: - remotePlugin( const QString & _plugin_executable ); + remotePlugin( const QString & _plugin_executable, + bool _wait_for_init_done = true ); virtual ~remotePlugin(); + inline void waitForInitDone( void ) + { + m_failed = waitForMessage( IdInitDone, TRUE ).id != IdInitDone; + } + virtual bool processMessage( const message & _m ); bool process( const sampleFrame * _in_buf, @@ -565,19 +610,28 @@ public: void updateSampleRate( sample_rate_t _sr ) { - message m( IdSampleRateInformation ); - m.addInt( _sr ); - sendMessage( m ); + lock(); + sendMessage( message( IdSampleRateInformation ).addInt( _sr ) ); + unlock(); } void showUI( void ) { + lock(); sendMessage( IdShowUI ); + unlock(); } void hideUI( void ) { + lock(); sendMessage( IdHideUI ); + unlock(); + } + + inline bool failed( void ) const + { + return( m_failed ); } @@ -592,6 +646,11 @@ protected: m_commMutex.unlock(); } + inline void setSplittedChannels( bool _on ) + { + m_splitChannels = _on; + } + private: void resizeSharedProcessingMemory( void ); @@ -603,6 +662,7 @@ private: QProcess m_process; QMutex m_commMutex; + bool m_splitChannels; #ifdef USE_NATIVE_SHMEM int m_shmID; #else @@ -642,14 +702,19 @@ public: return( m_shm ); } - virtual void updateSampleRate( sample_rate_t ) + virtual void updateSampleRate( void ) { } - virtual void updateBufferSize( fpp_t ) + virtual void updateBufferSize( void ) { } + inline sample_rate_t sampleRate( void ) const + { + return( m_sampleRate ); + } + inline fpp_t bufferSize( void ) const { return( m_bufferSize ); @@ -658,17 +723,23 @@ public: void setInputCount( int _i ) { m_inputCount = _i; - message m( IdChangeInputCount ); - m.addInt( _i ); - sendMessage( m ); + sendMessage( message( IdChangeInputCount ).addInt( _i ) ); } void setOutputCount( int _i ) { m_outputCount = _i; - message m( IdChangeOutputCount ); - m.addInt( _i ); - sendMessage( m ); + sendMessage( message( IdChangeOutputCount ).addInt( _i ) ); + } + + virtual int inputCount( void ) const + { + return( m_inputCount ); + } + + virtual int outputCount( void ) const + { + return( m_outputCount ); } @@ -684,6 +755,7 @@ private: int m_inputCount; int m_outputCount; + sample_rate_t m_sampleRate; fpp_t m_bufferSize; } ; @@ -724,9 +796,11 @@ void remotePluginBase::sendMessage( const message & _m ) m_out->lock(); m_out->writeInt( _m.id ); m_out->writeInt( _m.data.size() ); + int j = 0; for( int i = 0; i < _m.data.size(); ++i ) { m_out->writeString( _m.data[i] ); + j += _m.data[i].size(); } m_out->unlock(); m_out->messageSent(); @@ -797,9 +871,10 @@ remotePluginClient::remotePluginClient( key_t _shm_in, key_t _shm_out ) : m_shmObj(), #endif m_shm( NULL ), - m_inputCount( DEFAULT_CHANNELS ), - m_outputCount( DEFAULT_CHANNELS ), - m_bufferSize( DEFAULT_BUFFER_SIZE ) + m_inputCount( 0 ), + m_outputCount( 0 ), + m_sampleRate( 44100 ), + m_bufferSize( 0 ) { sendMessage( IdSampleRateInformation ); sendMessage( IdBufferSizeInformation ); @@ -810,7 +885,7 @@ remotePluginClient::remotePluginClient( key_t _shm_in, key_t _shm_out ) : remotePluginClient::~remotePluginClient() { - sendMessage( IdClosePlugin ); + sendMessage( IdQuit ); #ifdef USE_NATIVE_SHMEM shmdt( m_shm ); @@ -830,15 +905,16 @@ bool remotePluginClient::processMessage( const message & _m ) return( false ); case IdSampleRateInformation: - updateSampleRate( _m.getInt( 0 ) ); + m_sampleRate = _m.getInt(); + updateSampleRate(); break; case IdBufferSizeInformation: - m_bufferSize = _m.getInt( 0 ); - updateBufferSize( m_bufferSize ); + m_bufferSize = _m.getInt(); + updateBufferSize(); break; - case IdClosePlugin: + case IdQuit: return( false ); case IdMidiEvent: @@ -861,8 +937,13 @@ bool remotePluginClient::processMessage( const message & _m ) setShmKey( _m.getInt( 0 ), _m.getInt( 1 ) ); break; + case IdInitDone: + break; + case IdUndefined: default: + fprintf( stderr, "undefined message: %d\n", + (int) _m.id ); break; } if( reply ) diff --git a/src/core/remote_plugin.cpp b/src/core/remote_plugin.cpp index 52569ab95..e84ad8c44 100644 --- a/src/core/remote_plugin.cpp +++ b/src/core/remote_plugin.cpp @@ -26,7 +26,7 @@ #define COMPILE_REMOTE_PLUGIN_BASE #include "remote_plugin.h" -#include "lmmsconfig.h" +#include "mixer.h" #include "engine.h" #include "config_mgr.h" @@ -39,11 +39,13 @@ -remotePlugin::remotePlugin( const QString & _plugin_executable ) : +remotePlugin::remotePlugin( const QString & _plugin_executable, + bool _wait_for_init_done ) : remotePluginBase( new shmFifo(), new shmFifo() ), m_initialized( false ), m_failed( true ), m_commMutex( QMutex::Recursive ), + m_splitChannels( false ), #ifdef USE_NATIVE_SHMEM m_shmID( 0 ), #else @@ -66,7 +68,10 @@ remotePlugin::remotePlugin( const QString & _plugin_executable ) : resizeSharedProcessingMemory(); - m_failed = waitForMessage( IdInitDone ).id != IdInitDone; + if( _wait_for_init_done ) + { + waitForInitDone(); + } unlock(); } @@ -77,7 +82,7 @@ remotePlugin::~remotePlugin() { if( m_failed == false ) { - sendMessage( IdClosePlugin ); + sendMessage( IdQuit ); m_process.waitForFinished( 1000 ); if( m_process.state() != QProcess::NotRunning ) @@ -124,28 +129,48 @@ bool remotePlugin::process( const sampleFrame * _in_buf, memset( m_shm, 0, m_shmSize ); - ch_cnt_t inputs = tMax( m_inputCount, DEFAULT_CHANNELS ); + ch_cnt_t inputs = tMin( m_inputCount, DEFAULT_CHANNELS ); if( _in_buf != NULL && inputs > 0 ) { - for( ch_cnt_t ch = 0; ch < inputs; ++ch ) + if( m_splitChannels ) { - for( fpp_t frame = 0; frame < frames; ++frame ) + for( ch_cnt_t ch = 0; ch < inputs; ++ch ) { - m_shm[ch * frames + frame] = _in_buf[frame][ch]; + for( fpp_t frame = 0; frame < frames; ++frame ) + { + m_shm[ch * frames + frame] = + _in_buf[frame][ch]; + } + } + } + else if( inputs == DEFAULT_CHANNELS ) + { + memcpy( m_shm, _in_buf, frames * BYTES_PER_FRAME ); + } + else + { + sampleFrame * o = (sampleFrame *) m_shm; + for( ch_cnt_t ch = 0; ch < inputs; ++ch ) + { + for( fpp_t frame = 0; frame < frames; ++frame ) + { + o[frame][ch] = _in_buf[frame][ch]; + } } } } lock(); sendMessage( IdStartProcessing ); + unlock(); m_initialized = TRUE; if( _wait ) { waitForProcessingFinished( _out_buf ); } - unlock(); + return( TRUE ); } @@ -164,11 +189,28 @@ bool remotePlugin::waitForProcessingFinished( sampleFrame * _out_buf ) unlock(); const fpp_t frames = engine::getMixer()->framesPerPeriod(); - const ch_cnt_t outputs = tMax( m_outputCount, + const ch_cnt_t outputs = tMin( m_outputCount, DEFAULT_CHANNELS ); - sampleFrame * o = (sampleFrame *) ( m_shm + m_inputCount*frames ); - if( outputs != DEFAULT_CHANNELS ) + if( m_splitChannels ) { + 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]; + } + } + } + else if( outputs == DEFAULT_CHANNELS ) + { + memcpy( _out_buf, m_shm + m_inputCount * frames, + frames * BYTES_PER_FRAME ); + } + else + { + sampleFrame * o = (sampleFrame *) ( m_shm + + m_inputCount*frames ); // clear buffer, if plugin didn't fill up both channels engine::getMixer()->clearAudioBuffer( _out_buf, frames ); @@ -181,10 +223,6 @@ bool remotePlugin::waitForProcessingFinished( sampleFrame * _out_buf ) } } } - else - { - memcpy( _out_buf, o, frames * sizeof( sampleFrame ) ); - } return( TRUE ); } @@ -242,18 +280,13 @@ void remotePlugin::resizeSharedProcessingMemory( void ) m_shm = (float *) m_shmObj.data(); #endif m_shmSize = s; - message m( IdChangeSharedMemoryKey ); - m.addInt( shm_key ); - m.addInt( m_shmSize ); - sendMessage( m ); + sendMessage( message( IdChangeSharedMemoryKey ). + addInt( shm_key ).addInt( m_shmSize ) ); } - - - bool remotePlugin::processMessage( const message & _m ) { lock(); @@ -291,7 +324,7 @@ bool remotePlugin::processMessage( const message & _m ) break; case IdProcessingDone: - case IdClosePlugin: + case IdQuit: case IdUndefined: default: break;