* 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
This commit is contained in:
Tobias Doerffel
2008-09-03 16:04:56 +00:00
parent 8b4c4872a4
commit 014ecfa901
2 changed files with 165 additions and 51 deletions

View File

@@ -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 <vector>
#include <cstring>
#include <string>
#include <cassert>
@@ -74,6 +74,7 @@ typedef int32_t key_t;
#define EXPORT
#define COMPILE_REMOTE_PLUGIN_BASE
#else
#include <QtCore/QMutex>
#include <QtCore/QProcess>
#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<std::string> 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 )

View File

@@ -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<ch_cnt_t>( m_inputCount, DEFAULT_CHANNELS );
ch_cnt_t inputs = tMin<ch_cnt_t>( 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<ch_cnt_t>( m_outputCount,
const ch_cnt_t outputs = tMin<ch_cnt_t>( 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;