better VST support and bugfixes
git-svn-id: https://lmms.svn.sf.net/svnroot/lmms/trunk/lmms@77 0778d3d1-df1d-0410-868b-ea421aaaa00d
This commit is contained in:
@@ -126,7 +126,7 @@ bSynth::~bSynth()
|
||||
delete[] sample_shape;
|
||||
}
|
||||
|
||||
sampleType bSynth::nextStringSample( void )
|
||||
sample_t bSynth::nextStringSample( void )
|
||||
{
|
||||
|
||||
|
||||
@@ -135,7 +135,7 @@ sampleType bSynth::nextStringSample( void )
|
||||
sample_realindex -= sample_length;
|
||||
}
|
||||
|
||||
sampleType sample;
|
||||
sample_t sample;
|
||||
|
||||
if (interpolation) {
|
||||
|
||||
@@ -705,7 +705,7 @@ void bitInvader::playNote( notePlayHandle * _n )
|
||||
bSynth * ps = static_cast<bSynth *>( _n->m_pluginData );
|
||||
for( Uint32 frame = 0; frame < frames; ++frame )
|
||||
{
|
||||
const sampleType cur = ps->nextStringSample();
|
||||
const sample_t cur = ps->nextStringSample();
|
||||
for( Uint8 chnl = 0; chnl < DEFAULT_CHANNELS; ++chnl )
|
||||
{
|
||||
buf[frame][chnl] = cur;
|
||||
|
||||
@@ -56,7 +56,7 @@ public:
|
||||
bSynth(float* sample, int length, float _pitch, bool _interpolation, float factor);
|
||||
virtual ~bSynth();
|
||||
|
||||
sampleType nextStringSample();
|
||||
sample_t nextStringSample();
|
||||
|
||||
|
||||
private:
|
||||
|
||||
@@ -148,7 +148,7 @@ void pluckedStringSynth::playNote( notePlayHandle * _n )
|
||||
pluckSynth * ps = static_cast<pluckSynth *>( _n->m_pluginData );
|
||||
for( Uint32 frame = 0; frame < frames; ++frame )
|
||||
{
|
||||
const sampleType cur = ps->nextStringSample();
|
||||
const sample_t cur = ps->nextStringSample();
|
||||
for( Uint8 chnl = 0; chnl < DEFAULT_CHANNELS; ++chnl )
|
||||
{
|
||||
buf[frame][chnl] = cur;
|
||||
@@ -178,7 +178,7 @@ pluckSynth::delayLine * FASTCALL pluckSynth::initDelayLine( int _len )
|
||||
dl->length = _len;
|
||||
if( _len > 0 )
|
||||
{
|
||||
dl->data = new sampleType[_len];
|
||||
dl->data = new sample_t[_len];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -46,16 +46,16 @@ public:
|
||||
pluckSynth::freeDelayLine( m_lowerRail );
|
||||
}
|
||||
|
||||
inline sampleType nextStringSample( void )
|
||||
inline sample_t nextStringSample( void )
|
||||
{
|
||||
// Output at pickup position
|
||||
sampleType outsamp = rgDlAccess( m_upperRail, m_pickupLoc );
|
||||
sample_t outsamp = rgDlAccess( m_upperRail, m_pickupLoc );
|
||||
outsamp += lgDlAccess( m_lowerRail, m_pickupLoc );
|
||||
|
||||
// Sample traveling into "bridge"
|
||||
sampleType ym0 = lgDlAccess( m_lowerRail, 1 );
|
||||
sample_t ym0 = lgDlAccess( m_lowerRail, 1 );
|
||||
// Sample to "nut"
|
||||
sampleType ypM = rgDlAccess( m_upperRail,
|
||||
sample_t ypM = rgDlAccess( m_upperRail,
|
||||
m_upperRail->length - 2 );
|
||||
|
||||
// String state update
|
||||
@@ -72,10 +72,10 @@ public:
|
||||
private:
|
||||
struct delayLine
|
||||
{
|
||||
sampleType * data;
|
||||
sample_t * data;
|
||||
int length;
|
||||
sampleType * pointer;
|
||||
sampleType * end;
|
||||
sample_t * pointer;
|
||||
sample_t * end;
|
||||
} ;
|
||||
|
||||
delayLine * m_upperRail;
|
||||
@@ -100,9 +100,9 @@ private:
|
||||
* wave travels one sample to the left), turning the previous
|
||||
* position into an "effective" x = L position for the next
|
||||
* iteration. */
|
||||
static inline void lgDlUpdate( delayLine * _dl, sampleType _insamp )
|
||||
static inline void lgDlUpdate( delayLine * _dl, sample_t _insamp )
|
||||
{
|
||||
register sampleType * ptr = _dl->pointer;
|
||||
register sample_t * ptr = _dl->pointer;
|
||||
*ptr = _insamp;
|
||||
++ptr;
|
||||
if( ptr > _dl->end )
|
||||
@@ -118,9 +118,9 @@ private:
|
||||
* "effective" x = 0 position for the next iteration. The
|
||||
* "bridge-reflected" sample from lower delay-line is then placed
|
||||
* into this position. */
|
||||
static inline void rgDlUpdate( delayLine * _dl, sampleType _insamp )
|
||||
static inline void rgDlUpdate( delayLine * _dl, sample_t _insamp )
|
||||
{
|
||||
register sampleType * ptr = _dl->pointer;
|
||||
register sample_t * ptr = _dl->pointer;
|
||||
--ptr;
|
||||
if( ptr < _dl->data )
|
||||
{
|
||||
@@ -133,9 +133,9 @@ private:
|
||||
/* dlAccess(dl, position);
|
||||
* Returns sample "position" samples into delay-line's past.
|
||||
* Position "0" points to the most recently inserted sample. */
|
||||
static inline sampleType dlAccess( delayLine * _dl, int _position )
|
||||
static inline sample_t dlAccess( delayLine * _dl, int _position )
|
||||
{
|
||||
sampleType * outpos = _dl->pointer + _position;
|
||||
sample_t * outpos = _dl->pointer + _position;
|
||||
while( outpos < _dl->data )
|
||||
{
|
||||
outpos += _dl->length;
|
||||
@@ -163,7 +163,7 @@ private:
|
||||
* is equal to the current upper delay-line pointer position (x = 0).
|
||||
* In a right-going delay-line, position increases to the right, and
|
||||
* delay increases to the right => left = past and right = future. */
|
||||
static inline sampleType rgDlAccess( delayLine * _dl, int _position )
|
||||
static inline sample_t rgDlAccess( delayLine * _dl, int _position )
|
||||
{
|
||||
return( dlAccess( _dl, _position ) );
|
||||
}
|
||||
@@ -173,14 +173,14 @@ private:
|
||||
* is equal to the current lower delay-line pointer position (x = 0).
|
||||
* In a left-going delay-line, position increases to the right, and
|
||||
* delay DEcreases to the right => left = future and right = past. */
|
||||
static inline sampleType lgDlAccess( delayLine * _dl, int _position )
|
||||
static inline sample_t lgDlAccess( delayLine * _dl, int _position )
|
||||
{
|
||||
return( dlAccess( _dl, _position ) );
|
||||
}
|
||||
|
||||
static inline sampleType bridgeReflection( sampleType _insamp )
|
||||
static inline sample_t bridgeReflection( sample_t _insamp )
|
||||
{
|
||||
static sampleType state = 0.0f; // filter memory
|
||||
static sample_t state = 0.0f; // filter memory
|
||||
// Implement a one-pole lowpass with feedback coefficient = 0.5
|
||||
return( state = state*0.5f + _insamp*0.5f );
|
||||
}
|
||||
|
||||
@@ -1,3 +1,29 @@
|
||||
/*
|
||||
* communication.h - header file defining stuff concerning communication between
|
||||
* LVSL-server and -client
|
||||
*
|
||||
* Copyright (c) 2005-2006 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
* 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _COMMUNICATION_H
|
||||
#define _COMMUNICATION_H
|
||||
|
||||
@@ -79,6 +105,18 @@ struct vstParamProperties
|
||||
} ;
|
||||
|
||||
|
||||
enum hostLanguages
|
||||
{
|
||||
LVSL_LANG_ENGLISH = 1,
|
||||
LVSL_LANG_GERMAN,
|
||||
LVSL_LANG_FRENCH,
|
||||
LVSL_LANG_ITALIAN,
|
||||
LVSL_LANG_SPANISH,
|
||||
LVSL_LANG_JAPANESE
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
enum vstRemoteCommands
|
||||
{
|
||||
// client -> server
|
||||
@@ -90,6 +128,7 @@ enum vstRemoteCommands
|
||||
VST_SAMPLE_RATE,
|
||||
VST_BUFFER_SIZE,
|
||||
VST_BPM,
|
||||
VST_LANGUAGE,
|
||||
VST_GET_PARAMETER_COUNT = 20,
|
||||
VST_GET_PARAMETER_DUMP,
|
||||
VST_SET_PARAMETER_DUMP,
|
||||
@@ -103,6 +142,7 @@ enum vstRemoteCommands
|
||||
VST_INPUT_COUNT,
|
||||
VST_OUTPUT_COUNT,
|
||||
VST_PLUGIN_XID,
|
||||
VST_PLUGIN_EDITOR_GEOMETRY,
|
||||
VST_PROCESS_DONE,
|
||||
VST_PLUGIN_NAME,
|
||||
VST_PLUGIN_VERSION,
|
||||
|
||||
@@ -35,6 +35,8 @@
|
||||
#else
|
||||
|
||||
#include <qapplication.h>
|
||||
#include <qlocale.h>
|
||||
|
||||
#include "qxembed.h"
|
||||
|
||||
#define QX11EmbedWidget QXEmbed
|
||||
@@ -80,11 +82,12 @@
|
||||
|
||||
|
||||
|
||||
|
||||
remoteVSTPlugin::remoteVSTPlugin( const QString & _plugin ) :
|
||||
m_failed( TRUE ),
|
||||
m_plugin( _plugin ),
|
||||
m_pluginWidget( NULL ),
|
||||
m_pluginWID( 0 ),
|
||||
m_pluginXID( 0 ),
|
||||
m_pluginPID( -1 ),
|
||||
m_serverInFD( -1 ),
|
||||
m_serverOutFD( -1 ),
|
||||
@@ -132,6 +135,20 @@ remoteVSTPlugin::remoteVSTPlugin( const QString & _plugin ) :
|
||||
m_serverOutFD = m_pipes[0][1];
|
||||
|
||||
lock();
|
||||
|
||||
writeValueS<Sint16>( VST_LANGUAGE );
|
||||
hostLanguages hlang = LVSL_LANG_ENGLISH;
|
||||
switch( QLocale::system().language() )
|
||||
{
|
||||
case QLocale::German: hlang = LVSL_LANG_GERMAN; break;
|
||||
case QLocale::French: hlang = LVSL_LANG_FRENCH; break;
|
||||
case QLocale::Italian: hlang = LVSL_LANG_ITALIAN; break;
|
||||
case QLocale::Spanish: hlang = LVSL_LANG_SPANISH; break;
|
||||
case QLocale::Japanese: hlang = LVSL_LANG_JAPANESE; break;
|
||||
default: break;
|
||||
}
|
||||
writeValueS<hostLanguages>( hlang );
|
||||
|
||||
writeValueS<Sint16>( VST_LOAD_PLUGIN );
|
||||
writeStringS( m_plugin.
|
||||
#ifdef QT4
|
||||
@@ -210,8 +227,6 @@ remoteVSTPlugin::~remoteVSTPlugin()
|
||||
|
||||
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
|
||||
void remoteVSTPlugin::showEditor( void )
|
||||
{
|
||||
@@ -220,29 +235,21 @@ void remoteVSTPlugin::showEditor( void )
|
||||
m_pluginWidget->show();
|
||||
return;
|
||||
}
|
||||
if( m_pluginWID == 0 )
|
||||
|
||||
if( m_pluginXID == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
XWindowAttributes attr;
|
||||
XGetWindowAttributes(
|
||||
#ifdef QT4
|
||||
QX11Info::display(),
|
||||
#else
|
||||
qt_xdisplay(),
|
||||
#endif
|
||||
m_pluginWID, &attr );
|
||||
|
||||
m_pluginWidget = new QWidget( lmmsMainWin::inst()->workspace() );
|
||||
m_pluginWidget->setFixedSize( attr.width, attr.height );
|
||||
m_pluginWidget->setFixedSize( m_pluginGeometry );
|
||||
m_pluginWidget->setWindowTitle( name() );
|
||||
m_pluginWidget->show();
|
||||
|
||||
QX11EmbedWidget * xe = new QX11EmbedWidget( m_pluginWidget );
|
||||
xe->embedInto( m_pluginWID );
|
||||
xe->setFixedSize( attr.width, attr.height );
|
||||
xe->embedInto( m_pluginXID );
|
||||
xe->setFixedSize( m_pluginGeometry );
|
||||
//xe->setAutoDelete( FALSE );
|
||||
m_pluginWidget->show();
|
||||
xe->show();
|
||||
|
||||
lock();
|
||||
@@ -267,14 +274,14 @@ void remoteVSTPlugin::hideEditor( void )
|
||||
void remoteVSTPlugin::process( const sampleFrame * _in_buf,
|
||||
sampleFrame * _out_buf )
|
||||
{
|
||||
const Uint32 frames = mixer::inst()->framesPerAudioBuffer();
|
||||
const fpab_t frames = mixer::inst()->framesPerAudioBuffer();
|
||||
|
||||
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 later stage of this procedure
|
||||
// information like SHM-key etc.) until we process messages
|
||||
// in a later stage of this procedure
|
||||
if( m_shmSize == 0 && messagesLeft() == TRUE )
|
||||
{
|
||||
(void) processNextMessage();
|
||||
@@ -285,15 +292,15 @@ void remoteVSTPlugin::process( const sampleFrame * _in_buf,
|
||||
|
||||
memset( m_shm, 0, m_shmSize );
|
||||
|
||||
Uint8 inputs = tMax<Uint8>( m_inputCount, DEFAULT_CHANNELS );
|
||||
ch_cnt_t inputs = tMax<ch_cnt_t>( m_inputCount, DEFAULT_CHANNELS );
|
||||
|
||||
if( _in_buf != NULL && inputs > 0 )
|
||||
{
|
||||
for( Uint8 ch = 0; ch < inputs; ++ch )
|
||||
for( ch_cnt_t ch = 0; ch < inputs; ++ch )
|
||||
{
|
||||
for( Uint32 frame = 0; frame < frames; ++frame )
|
||||
for( fpab_t frame = 0; frame < frames; ++frame )
|
||||
{
|
||||
m_shm[ch*frames+frame] = _in_buf[frame][ch];
|
||||
m_shm[ch * frames + frame] = _in_buf[frame][ch];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -307,19 +314,21 @@ void remoteVSTPlugin::process( const sampleFrame * _in_buf,
|
||||
// wait until server signals that process()ing is done
|
||||
while( processNextMessage() != VST_PROCESS_DONE )
|
||||
{
|
||||
// allow better scheduling (we're just waiting)
|
||||
// hopefully scheduler gives process-time to plugin...
|
||||
usleep( 10 );
|
||||
}
|
||||
|
||||
Uint8 outputs = tMax<Uint8>( m_outputCount, DEFAULT_CHANNELS );
|
||||
ch_cnt_t outputs = tMax<ch_cnt_t>( m_outputCount,
|
||||
DEFAULT_CHANNELS );
|
||||
if( outputs != DEFAULT_CHANNELS )
|
||||
{
|
||||
// clear buffer, if plugin doesn't fill up both channels
|
||||
// clear buffer, if plugin didn't fill up both channels
|
||||
mixer::inst()->clearAudioBuffer( _out_buf, frames );
|
||||
}
|
||||
for( Uint8 ch = 0; ch < outputs; ++ch )
|
||||
|
||||
for( ch_cnt_t ch = 0; ch < outputs; ++ch )
|
||||
{
|
||||
for( Uint32 frame = 0; frame < frames; ++frame )
|
||||
for( fpab_t frame = 0; frame < frames; ++frame )
|
||||
{
|
||||
_out_buf[frame][ch] = m_shm[(m_inputCount+ch)*
|
||||
frames+frame];
|
||||
@@ -376,7 +385,7 @@ void remoteVSTPlugin::setParameterDump( const QMap<QString, QString> & _pdump )
|
||||
for( QMap<QString, QString>::const_iterator it = _pdump.begin();
|
||||
it != _pdump.end(); ++it )
|
||||
{
|
||||
vstParameterDumpItem dump_item =
|
||||
const vstParameterDumpItem dump_item =
|
||||
{
|
||||
( *it ).section( ':', 0, 0 ).toInt(),
|
||||
"",
|
||||
@@ -397,6 +406,7 @@ void remoteVSTPlugin::setShmKeyAndSize( Uint16 _key, size_t _size )
|
||||
m_shm = NULL;
|
||||
m_shmSize = 0;
|
||||
}
|
||||
|
||||
// only called for detaching SHM?
|
||||
if( _size == 0 )
|
||||
{
|
||||
@@ -418,14 +428,6 @@ void remoteVSTPlugin::setShmKeyAndSize( Uint16 _key, size_t _size )
|
||||
|
||||
|
||||
|
||||
void remoteVSTPlugin::setPluginXID( const Sint32 _plugin_xid )
|
||||
{
|
||||
m_pluginWID = _plugin_xid;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool remoteVSTPlugin::messagesLeft( void ) const
|
||||
{
|
||||
fd_set rfds;
|
||||
@@ -462,13 +464,14 @@ Sint16 remoteVSTPlugin::processNextMessage( void )
|
||||
case VST_GET_SAMPLE_RATE:
|
||||
writeValueS<Sint16>( VST_SAMPLE_RATE );
|
||||
// handle is the same
|
||||
writeValueS<Sint32>( mixer::inst()->sampleRate() );
|
||||
writeValueS<sample_rate_t>(
|
||||
mixer::inst()->sampleRate() );
|
||||
break;
|
||||
|
||||
case VST_GET_BUFFER_SIZE:
|
||||
writeValueS<Sint16>( VST_BUFFER_SIZE );
|
||||
// handle is the same
|
||||
writeValueS<Uint32>(
|
||||
writeValueS<fpab_t>(
|
||||
mixer::inst()->framesPerAudioBuffer() );
|
||||
break;
|
||||
|
||||
@@ -481,17 +484,36 @@ Sint16 remoteVSTPlugin::processNextMessage( void )
|
||||
}
|
||||
|
||||
case VST_INPUT_COUNT:
|
||||
m_inputCount = readValueS<Uint8>();
|
||||
m_inputCount = readValueS<ch_cnt_t>();
|
||||
break;
|
||||
|
||||
case VST_OUTPUT_COUNT:
|
||||
m_outputCount = readValueS<Uint8>();
|
||||
m_outputCount = readValueS<ch_cnt_t>();
|
||||
break;
|
||||
|
||||
case VST_PLUGIN_XID:
|
||||
setPluginXID( readValueS<Sint32>() );
|
||||
m_pluginXID = readValueS<Sint32>();
|
||||
break;
|
||||
|
||||
case VST_PLUGIN_EDITOR_GEOMETRY:
|
||||
{
|
||||
const Sint16 w = readValueS<Sint16>();
|
||||
const Sint16 h = readValueS<Sint16>();
|
||||
m_pluginGeometry = QSize( w, h );
|
||||
if( m_pluginWidget != NULL )
|
||||
{
|
||||
m_pluginWidget->setFixedSize(
|
||||
m_pluginGeometry );
|
||||
if( m_pluginWidget->childAt( 0, 0 ) != NULL )
|
||||
{
|
||||
m_pluginWidget->childAt( 0, 0
|
||||
)->setFixedSize(
|
||||
m_pluginGeometry );
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case VST_PLUGIN_NAME:
|
||||
m_name = readStringS().c_str();
|
||||
break;
|
||||
|
||||
@@ -144,14 +144,13 @@ private:
|
||||
Sint16 processNextMessage( void );
|
||||
|
||||
void FASTCALL setShmKeyAndSize( const Uint16 _key, const size_t _size );
|
||||
void FASTCALL setPluginXID( const Sint32 _plugin_xid );
|
||||
|
||||
|
||||
|
||||
bool m_failed;
|
||||
QString m_plugin;
|
||||
QWidget * m_pluginWidget;
|
||||
Sint32 m_pluginWID;
|
||||
Sint32 m_pluginXID;
|
||||
QSize m_pluginGeometry;
|
||||
|
||||
int m_pluginPID;
|
||||
int m_pipes[2][2];
|
||||
|
||||
@@ -56,19 +56,19 @@
|
||||
#include <signal.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SCHED_H
|
||||
#include <sched.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include <windows.h>
|
||||
#include <wine/exception.h>
|
||||
|
||||
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <string>
|
||||
|
||||
|
||||
#include "types.h"
|
||||
#include "midi.h"
|
||||
#include "communication.h"
|
||||
|
||||
|
||||
#include <aeffectx.h>
|
||||
|
||||
#if kVstVersion < 2400
|
||||
@@ -89,6 +89,11 @@ struct ERect
|
||||
#endif
|
||||
|
||||
|
||||
#include "types.h"
|
||||
#include "midi.h"
|
||||
#include "communication.h"
|
||||
|
||||
|
||||
#ifdef HAVE_TLS
|
||||
static __thread int ejmpbuf_valid = false;
|
||||
static __thread jmp_buf ejmpbuf;
|
||||
@@ -98,6 +103,9 @@ static pthread_key_t ejmpbuf_key;
|
||||
#endif
|
||||
|
||||
|
||||
static hostLanguages hlang = LVSL_LANG_ENGLISH;
|
||||
|
||||
|
||||
class VSTPlugin;
|
||||
|
||||
VSTPlugin * plugin = NULL;
|
||||
@@ -140,20 +148,21 @@ public:
|
||||
// enqueue given MIDI-event to be processed the next time process() is
|
||||
// called
|
||||
void enqueueMidiEvent( const midiEvent & _event,
|
||||
const Uint32 _frames_ahead );
|
||||
const f_cnt_t _frames_ahead );
|
||||
|
||||
// set given sample-rate for plugin
|
||||
void setSampleRate( const Sint32 _rate )
|
||||
void setSampleRate( const sample_rate_t _rate )
|
||||
{
|
||||
m_plugin->dispatcher( m_plugin, effSetSampleRate, 0, 0, NULL,
|
||||
(float) _rate );
|
||||
m_sampleRate = _rate;
|
||||
}
|
||||
|
||||
// set given block-size for plugin
|
||||
void setBlockSize( const Uint32 _bsize );
|
||||
void setBlockSize( const fpab_t _bsize );
|
||||
|
||||
// set given tempo
|
||||
void setBPM( const Uint16 _bpm )
|
||||
void setBPM( const bpm_t _bpm )
|
||||
{
|
||||
m_bpm = _bpm;
|
||||
}
|
||||
@@ -184,13 +193,13 @@ public:
|
||||
void getParameterProperties( const Sint32 _idx );
|
||||
|
||||
// number of inputs
|
||||
Uint8 inputCount( void ) const
|
||||
ch_cnt_t inputCount( void ) const
|
||||
{
|
||||
return( m_plugin->numInputs );
|
||||
}
|
||||
|
||||
// number of outputs
|
||||
Uint8 outputCount( void ) const
|
||||
ch_cnt_t outputCount( void ) const
|
||||
{
|
||||
return( m_plugin->numOutputs );
|
||||
}
|
||||
@@ -224,22 +233,26 @@ private:
|
||||
|
||||
AEffect * m_plugin;
|
||||
HWND m_window;
|
||||
int m_windowXID;
|
||||
Sint32 m_windowXID;
|
||||
Sint16 m_windowWidth;
|
||||
Sint16 m_windowHeight;
|
||||
|
||||
pthread_mutex_t m_lock;
|
||||
pthread_cond_t m_windowStatusChange;
|
||||
DWORD m_guiThreadID;
|
||||
|
||||
|
||||
Uint32 m_blockSize;
|
||||
fpab_t m_blockSize;
|
||||
float * m_shm;
|
||||
|
||||
float * * m_inputs;
|
||||
float * * m_outputs;
|
||||
|
||||
std::vector<VstMidiEvent> m_midiEvents;
|
||||
std::list<VstMidiEvent> m_midiEvents;
|
||||
|
||||
Uint16 m_bpm;
|
||||
bpm_t m_bpm;
|
||||
sample_rate_t m_sampleRate;
|
||||
double m_currentSamplePos;
|
||||
|
||||
} ;
|
||||
|
||||
@@ -252,6 +265,8 @@ VSTPlugin::VSTPlugin( const std::string & _plugin_file ) :
|
||||
m_plugin( NULL ),
|
||||
m_window( NULL ),
|
||||
m_windowXID( 0 ),
|
||||
m_windowWidth( 0 ),
|
||||
m_windowHeight( 0 ),
|
||||
m_lock(),
|
||||
m_windowStatusChange(),
|
||||
m_guiThreadID( 0 ),
|
||||
@@ -260,7 +275,9 @@ VSTPlugin::VSTPlugin( const std::string & _plugin_file ) :
|
||||
m_inputs( NULL ),
|
||||
m_outputs( NULL ),
|
||||
m_midiEvents(),
|
||||
m_bpm( 0 )
|
||||
m_bpm( 0 ),
|
||||
m_sampleRate( 44100 ),
|
||||
m_currentSamplePos( 0 )
|
||||
{
|
||||
if( load( _plugin_file ) == false )
|
||||
{
|
||||
@@ -293,6 +310,13 @@ VSTPlugin::VSTPlugin( const std::string & _plugin_file ) :
|
||||
writeValue<Sint16>( VST_PLUGIN_XID );
|
||||
writeValue<Sint32>( m_windowXID );
|
||||
|
||||
if( m_windowXID != 0 )
|
||||
{
|
||||
writeValue<Sint16>( VST_PLUGIN_EDITOR_GEOMETRY );
|
||||
writeValue<Sint16>( m_windowWidth );
|
||||
writeValue<Sint16>( m_windowHeight );
|
||||
}
|
||||
|
||||
writeValue<Sint16>( VST_PLUGIN_NAME );
|
||||
writeString( pluginName() );
|
||||
|
||||
@@ -364,9 +388,9 @@ bool VSTPlugin::load( const std::string & _plugin_file )
|
||||
m_shortName = basename( tmp );
|
||||
free( tmp );
|
||||
|
||||
typedef AEffect * ( * mainEntry )( audioMasterCallback );
|
||||
typedef AEffect * ( __stdcall * mainEntry )( audioMasterCallback );
|
||||
mainEntry main_entry = (mainEntry) GetProcAddress( m_libInst,
|
||||
"main" );
|
||||
"main" );
|
||||
if( main_entry == NULL )
|
||||
{
|
||||
return( false );
|
||||
@@ -402,19 +426,22 @@ void VSTPlugin::process( void )
|
||||
// dispatcher-call, so we create static copies of the
|
||||
// data and post them
|
||||
#define MIDI_EVENT_BUFFER_COUNT 1024
|
||||
static char event_buf[sizeof(VstMidiEvent * ) *
|
||||
static char event_buf[sizeof( VstMidiEvent * ) *
|
||||
MIDI_EVENT_BUFFER_COUNT +
|
||||
sizeof( VstEvents )];
|
||||
static VstMidiEvent vme[MIDI_EVENT_BUFFER_COUNT];
|
||||
VstEvents * events = (VstEvents *) event_buf;
|
||||
events->reserved = 0;
|
||||
events->numEvents = m_midiEvents.size();
|
||||
for( unsigned int i = 0; i < m_midiEvents.size(); ++i )
|
||||
Sint16 idx = 0;
|
||||
for( std::list<VstMidiEvent>::iterator it =
|
||||
m_midiEvents.begin();
|
||||
it != m_midiEvents.end(); ++it, ++idx )
|
||||
{
|
||||
memcpy( &vme[i], &m_midiEvents[i],
|
||||
sizeof( VstMidiEvent ) );
|
||||
events->events[i] = (VstEvent *) &vme[i];
|
||||
memcpy( &vme[idx], &*it, sizeof( VstMidiEvent ) );
|
||||
events->events[idx] = (VstEvent *) &vme[idx];
|
||||
}
|
||||
|
||||
m_midiEvents.clear();
|
||||
m_plugin->dispatcher( m_plugin, effProcessEvents, 0, 0, events,
|
||||
0.0f );
|
||||
@@ -422,15 +449,14 @@ void VSTPlugin::process( void )
|
||||
|
||||
// now we're ready to fetch sound from VST-plugin
|
||||
|
||||
for( int i = 0; i < inputCount(); ++i )
|
||||
for( ch_cnt_t i = 0; i < inputCount(); ++i )
|
||||
{
|
||||
m_inputs[i] = &m_shm[i * m_blockSize];
|
||||
}
|
||||
|
||||
for( int i = 0; i < outputCount(); ++i )
|
||||
for( ch_cnt_t i = 0; i < outputCount(); ++i )
|
||||
{
|
||||
m_outputs[i] = &m_shm[( i + inputCount() ) *
|
||||
m_blockSize];
|
||||
m_outputs[i] = &m_shm[( i + inputCount() ) * m_blockSize];
|
||||
}
|
||||
|
||||
#ifdef OLD_VST_SDK
|
||||
@@ -449,6 +475,8 @@ void VSTPlugin::process( void )
|
||||
}
|
||||
#endif
|
||||
|
||||
m_currentSamplePos += m_blockSize;
|
||||
|
||||
writeValue<Sint16>( VST_PROCESS_DONE );
|
||||
|
||||
// give plugin some idle-time for GUI-update and so on...
|
||||
@@ -460,7 +488,7 @@ void VSTPlugin::process( void )
|
||||
|
||||
|
||||
void VSTPlugin::enqueueMidiEvent( const midiEvent & _event,
|
||||
const Uint32 _frames_ahead )
|
||||
const f_cnt_t _frames_ahead )
|
||||
{
|
||||
VstMidiEvent event;
|
||||
|
||||
@@ -484,12 +512,13 @@ void VSTPlugin::enqueueMidiEvent( const midiEvent & _event,
|
||||
|
||||
|
||||
|
||||
void VSTPlugin::setBlockSize( const Uint32 _bsize )
|
||||
void VSTPlugin::setBlockSize( const Uint16 _bsize )
|
||||
{
|
||||
if( _bsize == m_blockSize )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_blockSize = _bsize;
|
||||
resizeSharedMemory();
|
||||
m_plugin->dispatcher( m_plugin, effSetBlockSize, 0, _bsize, NULL,
|
||||
@@ -612,7 +641,7 @@ void VSTPlugin::resizeSharedMemory( void )
|
||||
int shm_id;
|
||||
Uint16 shm_key = 0;
|
||||
while( ( shm_id = shmget( ++shm_key, s, IPC_CREAT | IPC_EXCL |
|
||||
0666 ) ) == -1 )
|
||||
0666 ) ) == -1 )
|
||||
{
|
||||
}
|
||||
|
||||
@@ -628,10 +657,10 @@ void VSTPlugin::resizeSharedMemory( void )
|
||||
}
|
||||
|
||||
writeValue<Sint16>( VST_INPUT_COUNT );
|
||||
writeValue<Uint8>( inputCount() );
|
||||
writeValue<ch_cnt_t>( inputCount() );
|
||||
|
||||
writeValue<Sint16>( VST_OUTPUT_COUNT );
|
||||
writeValue<Uint8>( outputCount() );
|
||||
writeValue<ch_cnt_t>( outputCount() );
|
||||
|
||||
writeValue<Sint16>( VST_SHM_KEY_AND_SIZE );
|
||||
writeValue<Uint16>( shm_key );
|
||||
@@ -648,6 +677,13 @@ void VSTPlugin::resizeSharedMemory( void )
|
||||
#endif
|
||||
|
||||
|
||||
/* TODO:
|
||||
* - complete audioMasterGetTime-handling (bars etc.)
|
||||
* - implement audioMasterProcessEvents
|
||||
* - audioMasterGetVendorVersion: return LMMS-version (config.h!)
|
||||
* - audioMasterGetDirectory: return either VST-plugin-dir or LMMS-workingdir
|
||||
* - audioMasterOpenFileSelector: show QFileDialog?
|
||||
*/
|
||||
VstIntPtr VSTPlugin::hostCallback( AEffect * _effect, VstInt32 _opcode,
|
||||
VstInt32 _index, VstIntPtr _value,
|
||||
void * _ptr, float _opt )
|
||||
@@ -664,8 +700,7 @@ VstIntPtr VSTPlugin::hostCallback( AEffect * _effect, VstInt32 _opcode,
|
||||
|
||||
case audioMasterVersion:
|
||||
//SHOW_CALLBACK( "amc: audioMasterVersion\n" );
|
||||
// vst version, currently 2 (0 for older)
|
||||
return( 2 );
|
||||
return( 2300 );
|
||||
|
||||
case audioMasterCurrentId:
|
||||
SHOW_CALLBACK( "amc: audioMasterCurrentId\n" );
|
||||
@@ -682,7 +717,7 @@ VstIntPtr VSTPlugin::hostCallback( AEffect * _effect, VstInt32 _opcode,
|
||||
return( 0 );
|
||||
|
||||
case audioMasterPinConnected:
|
||||
SHOW_CALLBACK( "amc: audioMasterPinConnected\n" );
|
||||
//SHOW_CALLBACK( "amc: audioMasterPinConnected\n" );
|
||||
// inquire if an input or output is beeing connected;
|
||||
// index enumerates input or output counting from zero:
|
||||
// value is 0 for input and != 0 otherwise. note: the
|
||||
@@ -699,8 +734,8 @@ VstIntPtr VSTPlugin::hostCallback( AEffect * _effect, VstInt32 _opcode,
|
||||
|
||||
memset( &_timeInfo, 0, sizeof( _timeInfo ) );
|
||||
|
||||
_timeInfo.samplePos = 0;
|
||||
// TODO: _timeInfo.sampleRate = mixer::inst()->sampleRate();
|
||||
_timeInfo.samplePos = plugin->m_currentSamplePos;
|
||||
_timeInfo.sampleRate = plugin->m_sampleRate;
|
||||
_timeInfo.flags = 0;
|
||||
_timeInfo.tempo = plugin->m_bpm;
|
||||
_timeInfo.timeSigNumerator = 4;
|
||||
@@ -717,7 +752,7 @@ VstIntPtr VSTPlugin::hostCallback( AEffect * _effect, VstInt32 _opcode,
|
||||
|
||||
case audioMasterIOChanged:
|
||||
plugin->resizeSharedMemory();
|
||||
SHOW_CALLBACK( "amc: audioMasterIOChanged\n" );
|
||||
//SHOW_CALLBACK( "amc: audioMasterIOChanged\n" );
|
||||
// numInputs and/or numOutputs has changed
|
||||
return( 0 );
|
||||
|
||||
@@ -725,21 +760,22 @@ VstIntPtr VSTPlugin::hostCallback( AEffect * _effect, VstInt32 _opcode,
|
||||
case audioMasterWantMidi:
|
||||
//SHOW_CALLBACK( "amc: audioMasterWantMidi\n" );
|
||||
// <value> is a filter which is currently ignored
|
||||
return( 0 );
|
||||
return( 1 );
|
||||
|
||||
case audioMasterSetTime:
|
||||
SHOW_CALLBACK( "amc: audioMasterSetTime\n" );
|
||||
// VstTimenfo* in <ptr>, filter in <value>, not
|
||||
// supported
|
||||
return( 0 );
|
||||
|
||||
case audioMasterTempoAt:
|
||||
SHOW_CALLBACK( "amc: audioMasterTempoAt\n" );
|
||||
//SHOW_CALLBACK( "amc: audioMasterTempoAt\n" );
|
||||
return( plugin->m_bpm * 10000 );
|
||||
|
||||
case audioMasterGetNumAutomatableParameters:
|
||||
SHOW_CALLBACK( "amc: audioMasterGetNumAutomatable"
|
||||
"Parameters\n" );
|
||||
return( 0 );
|
||||
return( 5000 );
|
||||
|
||||
case audioMasterGetParameterQuantization:
|
||||
SHOW_CALLBACK( "amc: audioMasterGetParameter\n"
|
||||
@@ -748,12 +784,12 @@ VstIntPtr VSTPlugin::hostCallback( AEffect * _effect, VstInt32 _opcode,
|
||||
// or 1 if full single float precision is maintained
|
||||
// in automation. parameter index in <value> (-1: all,
|
||||
// any)
|
||||
return( 0 );
|
||||
return( 1 );
|
||||
|
||||
case audioMasterNeedIdle:
|
||||
//SHOW_CALLBACK( "amc: audioMasterNeedIdle\n" );
|
||||
// plug needs idle calls (outside its editor window)
|
||||
return( 0 );
|
||||
return( 1 );
|
||||
|
||||
case audioMasterGetPreviousPlug:
|
||||
SHOW_CALLBACK( "amc: audioMasterGetPreviousPlug\n" );
|
||||
@@ -805,30 +841,37 @@ VstIntPtr VSTPlugin::hostCallback( AEffect * _effect, VstInt32 _opcode,
|
||||
#endif
|
||||
|
||||
case audioMasterSizeWindow:
|
||||
// TODO using lmms-main-window-size
|
||||
SHOW_CALLBACK( "amc: audioMasterSizeWindow\n" );
|
||||
// index: width, value: height
|
||||
return( 0 );
|
||||
//SHOW_CALLBACK( "amc: audioMasterSizeWindow\n" );
|
||||
if( plugin->m_window == 0 )
|
||||
{
|
||||
return( 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<Sint16>( VST_PLUGIN_EDITOR_GEOMETRY );
|
||||
writeValue<Sint16>( plugin->m_windowWidth );
|
||||
writeValue<Sint16>( plugin->m_windowHeight );
|
||||
return( 1 );
|
||||
|
||||
case audioMasterGetSampleRate:
|
||||
// TODO using mixer-call
|
||||
SHOW_CALLBACK( "amc: audioMasterGetSampleRate\n" );
|
||||
return( 0 );
|
||||
//SHOW_CALLBACK( "amc: audioMasterGetSampleRate\n" );
|
||||
return( plugin->m_sampleRate );
|
||||
|
||||
case audioMasterGetBlockSize:
|
||||
// TODO using mixer-call
|
||||
SHOW_CALLBACK( "amc: audioMasterGetBlockSize\n" );
|
||||
return( 0 );
|
||||
//SHOW_CALLBACK( "amc: audioMasterGetBlockSize\n" );
|
||||
return( plugin->m_blockSize );
|
||||
|
||||
case audioMasterGetInputLatency:
|
||||
// TODO using mixer-call
|
||||
SHOW_CALLBACK( "amc: audioMasterGetInputLatency\n" );
|
||||
return( 0 );
|
||||
//SHOW_CALLBACK( "amc: audioMasterGetInputLatency\n" );
|
||||
return( plugin->m_blockSize );
|
||||
|
||||
case audioMasterGetOutputLatency:
|
||||
// TODO using mixer-call
|
||||
SHOW_CALLBACK( "amc: audioMasterGetOutputLatency\n" );
|
||||
return( 0 );
|
||||
//SHOW_CALLBACK( "amc: audioMasterGetOutputLatency\n" );
|
||||
return( plugin->m_blockSize );
|
||||
|
||||
case audioMasterGetCurrentProcessLevel:
|
||||
SHOW_CALLBACK( "amc: audioMasterGetCurrentProcess"
|
||||
@@ -876,22 +919,22 @@ VstIntPtr VSTPlugin::hostCallback( AEffect * _effect, VstInt32 _opcode,
|
||||
return( 0 );
|
||||
|
||||
case audioMasterGetVendorString:
|
||||
SHOW_CALLBACK( "amc: audioMasterGetVendorString\n" );
|
||||
//SHOW_CALLBACK( "amc: audioMasterGetVendorString\n" );
|
||||
// fills <ptr> with a string identifying the vendor
|
||||
// (max 64 char)
|
||||
strcpy( (char *) _ptr, "LAD");
|
||||
return( 0 );
|
||||
strcpy( (char *) _ptr, "Tobias Doerffel & others");
|
||||
return( 1 );
|
||||
|
||||
case audioMasterGetProductString:
|
||||
SHOW_CALLBACK( "amc: audioMasterGetProductString\n" );
|
||||
//SHOW_CALLBACK( "amc: audioMasterGetProductString\n" );
|
||||
// fills <ptr> with a string with product name
|
||||
// (max 64 char)
|
||||
strcpy( (char *) _ptr, "XFST-Server" );
|
||||
return( 0 );
|
||||
strcpy( (char *) _ptr,
|
||||
"LMMS VST Support Layer (LVSL)" );
|
||||
return( 1 );
|
||||
|
||||
case audioMasterGetVendorVersion:
|
||||
SHOW_CALLBACK( "amc: audioMasterGetVendorVersion\n" );
|
||||
// TODO
|
||||
// returns vendor-specific version
|
||||
return( 1000 );
|
||||
|
||||
@@ -901,19 +944,18 @@ VstIntPtr VSTPlugin::hostCallback( AEffect * _effect, VstInt32 _opcode,
|
||||
return( 0 );
|
||||
|
||||
case audioMasterCanDo:
|
||||
SHOW_CALLBACK( "amc: audioMasterCanDo\n" );
|
||||
// string in ptr, see below
|
||||
return( 0 );
|
||||
|
||||
//SHOW_CALLBACK( "amc: audioMasterCanDo\n" );
|
||||
return( !strcmp( (char *) _ptr, "sendVstEvents" ) ||
|
||||
!strcmp( (char *) _ptr, "sendVstMidiEvent" ) ||
|
||||
!strcmp( (char *) _ptr, "sendVstTimeInfo" ) ||
|
||||
!strcmp( (char *) _ptr, "sizeWindow" ) );
|
||||
|
||||
case audioMasterGetLanguage:
|
||||
SHOW_CALLBACK( "amc: audioMasterGetLanguage\n" );
|
||||
// TODO
|
||||
// see enum
|
||||
return( 0 );
|
||||
//SHOW_CALLBACK( "amc: audioMasterGetLanguage\n" );
|
||||
return( hlang );
|
||||
|
||||
case audioMasterGetDirectory:
|
||||
SHOW_CALLBACK( "amc: audioMasterGetDirectory\n" );
|
||||
// TODO
|
||||
// get plug directory, FSSpec on MAC, else char*
|
||||
return( 0 );
|
||||
|
||||
@@ -1015,7 +1057,7 @@ DWORD WINAPI VSTPlugin::guiEventLoop( LPVOID _param )
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
_this->m_windowXID = (int) GetPropA( _this->m_window,
|
||||
_this->m_windowXID = (Sint32) GetPropA( _this->m_window,
|
||||
"__wine_x11_whole_window" );
|
||||
|
||||
|
||||
@@ -1026,13 +1068,18 @@ DWORD WINAPI VSTPlugin::guiEventLoop( LPVOID _param )
|
||||
_this->m_plugin->dispatcher( _this->m_plugin, effEditGetRect, 0, 0,
|
||||
&er, 0 );
|
||||
|
||||
/* const int width = er->right - er->left;
|
||||
const int height = er->bottom - er->top;*/
|
||||
_this->m_windowWidth = er->right - er->left;
|
||||
_this->m_windowHeight = er->bottom - er->top;
|
||||
|
||||
SetWindowPos( _this->m_window, 0, 0, 0, er->right - er->left + 8,
|
||||
er->bottom-er->top + 26, SWP_NOACTIVATE | SWP_NOREDRAW |
|
||||
SWP_NOMOVE | SWP_NOZORDER );
|
||||
SetWindowPos( _this->m_window, 0, 0, 0, _this->m_windowWidth + 8,
|
||||
_this->m_windowHeight + 26,
|
||||
SWP_NOACTIVATE /*| SWP_NOREDRAW*/ | SWP_NOMOVE |
|
||||
SWP_NOOWNERZORDER | SWP_NOZORDER );
|
||||
#ifdef HAVE_TLS
|
||||
ejmpbuf_valid = false;
|
||||
#else
|
||||
*ejmpbuf_valid = false;
|
||||
#endif
|
||||
|
||||
pthread_cond_signal( &_this->m_windowStatusChange );
|
||||
|
||||
@@ -1050,7 +1097,9 @@ DWORD WINAPI VSTPlugin::guiEventLoop( LPVOID _param )
|
||||
switch( msg.wParam )
|
||||
{
|
||||
case SHOW_EDITOR:
|
||||
ShowWindow( _this->m_window, SW_SHOW );
|
||||
ShowWindow( _this->m_window,
|
||||
SW_SHOWNORMAL );
|
||||
UpdateWindow( _this->m_window );
|
||||
break;
|
||||
|
||||
case CLOSE_PLUGIN:
|
||||
@@ -1098,6 +1147,17 @@ int main( void )
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
#ifdef HAVE_SCHED_H
|
||||
// try to set realtime-priority
|
||||
struct sched_param sparam;
|
||||
sparam.sched_priority = ( sched_get_priority_max( SCHED_FIFO ) +
|
||||
sched_get_priority_min( SCHED_FIFO ) ) / 2;
|
||||
if( sched_setscheduler( 0, SCHED_FIFO, &sparam ) == -1 )
|
||||
{
|
||||
lvsMessage( "could not set realtime priority for VST-server" );
|
||||
}
|
||||
#endif
|
||||
|
||||
Sint16 cmd;
|
||||
while( ( cmd = readValue<Sint16>() ) != VST_CLOSE_PLUGIN )
|
||||
{
|
||||
@@ -1118,22 +1178,27 @@ int main( void )
|
||||
case VST_ENQUEUE_MIDI_EVENT:
|
||||
{
|
||||
const midiEvent ev = readValue<midiEvent>();
|
||||
const Uint32 fr_ahead = readValue<Uint32>();
|
||||
const f_cnt_t fr_ahead = readValue<f_cnt_t>();
|
||||
plugin->enqueueMidiEvent( ev, fr_ahead );
|
||||
break;
|
||||
}
|
||||
|
||||
case VST_SAMPLE_RATE:
|
||||
plugin->setSampleRate( readValue<Sint32>() );
|
||||
plugin->setSampleRate(
|
||||
readValue<sample_rate_t>() );
|
||||
break;
|
||||
|
||||
|
||||
case VST_BUFFER_SIZE:
|
||||
plugin->setBlockSize( readValue<Uint32>() );
|
||||
plugin->setBlockSize( readValue<fpab_t>() );
|
||||
break;
|
||||
|
||||
case VST_BPM:
|
||||
plugin->setBPM( readValue<Uint16>() );
|
||||
plugin->setBPM( readValue<bpm_t>() );
|
||||
break;
|
||||
|
||||
case VST_LANGUAGE:
|
||||
hlang = readValue<hostLanguages>();
|
||||
break;
|
||||
|
||||
case VST_GET_PARAMETER_DUMP:
|
||||
|
||||
Reference in New Issue
Block a user