* 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:
@@ -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 )
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user