Merge branch 'win64-vst'

* win64-vst:
  VST support layer: fixed non-working 64 bit VST plugins
  VST support layer: added 32 bit VST plugin support for Win64
  Win64Toolchain: added 32 bit compiler configuration
  ZynAddSubFX: use new RemotePlugin::init() method
  RemotePlugin: added support for running remote process multiple times
(cherry picked from commit 65c073ec63)
This commit is contained in:
Tobias Doerffel
2010-12-26 11:22:39 +01:00
parent 269234fd09
commit 65a0313807
12 changed files with 170 additions and 96 deletions

View File

@@ -13,6 +13,13 @@ SET(MINGW_TOOL_PREFIX ${MINGW_PREFIX}/bin/${CMAKE_SYSTEM_PROCESSOR}-w64-mingw32
SET(CMAKE_C_COMPILER ${MINGW_TOOL_PREFIX}gcc)
SET(CMAKE_CXX_COMPILER ${MINGW_TOOL_PREFIX}g++)
IF(WIN64)
# specify the cross compiler
SET(MINGW_TOOL_PREFIX32 ${MINGW_PREFIX32}/bin/${CMAKE_SYSTEM_PROCESSOR32}-w64-mingw32-)
SET(CMAKE_C_COMPILER32 ${MINGW_TOOL_PREFIX32}gcc)
SET(CMAKE_CXX_COMPILER32 ${MINGW_TOOL_PREFIX32}g++)
ENDIF()
# specify location of some tools
SET(STRIP ${MINGW_TOOL_PREFIX}strip)
SET(WINDRES ${MINGW_TOOL_PREFIX}windres)

View File

@@ -1,6 +1,8 @@
SET(MINGW_PREFIX /opt/mingw64)
SET(MINGW_PREFIX32 /opt/mingw32)
SET(CMAKE_SYSTEM_PROCESSOR x86_64)
SET(CMAKE_SYSTEM_PROCESSOR32 i686)
SET(WIN64 TRUE)

View File

@@ -1,7 +1,7 @@
/*
* RemotePlugin.h - base class providing RPC like mechanisms
*
* Copyright (c) 2008-2009 Tobias Doerffel <tobydox/at/users.sourceforge.net>
* Copyright (c) 2008-2010 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*
@@ -602,6 +602,14 @@ public:
RemotePluginBase( shmFifo * _in, shmFifo * _out );
virtual ~RemotePluginBase();
void reset( shmFifo *in, shmFifo *out )
{
delete m_in;
delete m_out;
m_in = in;
m_out = out;
}
void sendMessage( const message & _m );
message receiveMessage();
@@ -695,8 +703,7 @@ private:
class EXPORT RemotePlugin : public RemotePluginBase
{
public:
RemotePlugin( const QString & _plugin_executable,
bool _wait_for_init_done = true );
RemotePlugin();
virtual ~RemotePlugin();
inline bool isRunning()
@@ -708,10 +715,11 @@ public:
#endif
}
inline void waitForInitDone( bool _busy_waiting = true )
bool init( const QString &pluginExecutable, bool waitForInitDoneMsg );
inline void waitForInitDone( bool _busyWaiting = true )
{
m_failed = waitForMessage( IdInitDone,
_busy_waiting ).id != IdInitDone;
m_failed = waitForMessage( IdInitDone, _busyWaiting ).id != IdInitDone;
}
virtual bool processMessage( const message & _m );

View File

@@ -167,7 +167,7 @@ public:
// 00
int numEvents;
// 04
int reserved;
void *reserved;
// 08
VstEvent * events[];
@@ -203,7 +203,7 @@ public:
// 00-03
int magic;
// dispatcher 04-07
int (* dispatcher)( AEffect * , int , int , int , void * , float );
intptr_t (* dispatcher)( AEffect * , int , int , intptr_t, void * , float );
// process, quite sure 08-0b
void (* process)( AEffect * , float * * , float * * , int );
// setParameter 0c-0f
@@ -221,15 +221,16 @@ public:
// flags 24-27
int flags;
// Fill somewhere 28-2b
RemoteVstPlugin * user;
void *ptr1;
void *ptr2;
// Zeroes 2c-2f 30-33 34-37 38-3b
char empty3[4 + 4 + 4 + 4];
char empty3[4 + 4 + 4];
// 1.0f 3c-3f
float unkown_float;
// An object? pointer 40-43
char empty4[4];
void *ptr3;
// Zeroes 44-47
char empty5[4];
void *user;
// Id 48-4b
int32_t uniqueID;
// Don't know 4c-4f
@@ -268,13 +269,7 @@ public:
typedef long int (* audioMasterCallback)( AEffect * , long int , long int ,
long int , void * , float );
// we don't use it, may be noise
#define VSTCALLBACK
typedef intptr_t (* audioMasterCallback)( AEffect * , int32_t, int32_t, intptr_t, void * , float );
#endif

View File

@@ -2,17 +2,22 @@ IF(LMMS_SUPPORT_VST)
INCLUDE(BuildPlugin)
BUILD_PLUGIN(vstbase vst_base.cpp VstPlugin.cpp VstPlugin.h communication.h MOCFILES VstPlugin.h)
IF(LMMS_BUILD_WIN32)
ADD_DEFINITIONS(-DPTW32_STATIC_LIB)
LINK_LIBRARIES(-lQtCore4 -lpthread -lgdi32 -lws2_32)
ADD_EXECUTABLE(remote_vst_plugin ${CMAKE_CURRENT_SOURCE_DIR}/remote_vst_plugin.cpp)
ADD_CUSTOM_COMMAND(TARGET remote_vst_plugin POST_BUILD COMMAND ${STRIP} ${CMAKE_CURRENT_BINARY_DIR}/remote_vst_plugin.exe)
INSTALL(TARGETS remote_vst_plugin RUNTIME DESTINATION ${PLUGIN_DIR})
ADD_EXECUTABLE(RemoteVstPlugin ${CMAKE_CURRENT_SOURCE_DIR}/RemoteVstPlugin.cpp)
ADD_CUSTOM_COMMAND(TARGET RemoteVstPlugin POST_BUILD COMMAND ${STRIP} ${CMAKE_CURRENT_BINARY_DIR}/RemoteVstPlugin.exe)
INSTALL(TARGETS RemoteVstPlugin RUNTIME DESTINATION ${PLUGIN_DIR})
IF(LMMS_BUILD_WIN64)
# build 32 bit version of RemoteVstPlugin for Win64 so we can load
# 32 bit VST plugins
ADD_SUBDIRECTORY(Win64)
ENDIF(LMMS_BUILD_WIN64)
ENDIF(LMMS_BUILD_WIN32)
BUILD_PLUGIN(vstbase vst_base.cpp VstPlugin.cpp VstPlugin.h communication.h MOCFILES VstPlugin.h)
IF(LMMS_BUILD_LINUX AND NOT WANT_VST_NOWINE)
@@ -20,17 +25,17 @@ IF(LMMS_HOST_X86_64)
SET(EXTRA_FLAGS -m32)
ENDIF(LMMS_HOST_X86_64)
ADD_CUSTOM_COMMAND(
SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/remote_vst_plugin.cpp
SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/RemoteVstPlugin.cpp
COMMAND wineg++
ARGS -I${CMAKE_BINARY_DIR} -I${CMAKE_SOURCE_DIR}/include -I${CMAKE_INSTALL_PREFIX}/include/wine/windows -I${CMAKE_INSTALL_PREFIX}/include -I/usr/include/wine/windows ${CMAKE_CURRENT_SOURCE_DIR}/remote_vst_plugin.cpp -mwindows -lpthread ${EXTRA_FLAGS} -o remote_vst_plugin
COMMAND find -name remote_vst_plugin.exe -exec mv "'{}'" remote_vst_plugin "';'"
ARGS -I${CMAKE_BINARY_DIR} -I${CMAKE_SOURCE_DIR}/include -I${CMAKE_INSTALL_PREFIX}/include/wine/windows -I${CMAKE_INSTALL_PREFIX}/include -I/usr/include/wine/windows ${CMAKE_CURRENT_SOURCE_DIR}/RemoteVstPlugin.cpp -mwindows -lpthread ${EXTRA_FLAGS} -o RemoteVstPlugin
COMMAND find -name RemoteVstPlugin.exe -exec mv "'{}'" RemoteVstPlugin "';'"
TARGET vstbase
OUTPUTS remote_vst_plugin
OUTPUTS RemoteVstPlugin
)
SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES remote_vst_plugin.exe.so)
SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES RemoteVstPlugin.exe.so)
INSTALL(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/remote_vst_plugin ${CMAKE_CURRENT_BINARY_DIR}/remote_vst_plugin.exe.so DESTINATION ${PLUGIN_DIR})
INSTALL(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/RemoteVstPlugin ${CMAKE_CURRENT_BINARY_DIR}/RemoteVstPlugin.exe.so DESTINATION ${PLUGIN_DIR})
ENDIF(LMMS_BUILD_LINUX AND NOT WANT_VST_NOWINE)

View File

@@ -1,8 +1,8 @@
/*
* remote_vst_plugin.cpp - LMMS VST Support Layer (RemotePlugin client)
* RemoteVstPlugin.cpp - LMMS VST Support Layer (RemotePlugin client)
*
* Copyright (c) 2005-2010 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* Copyright (c) 2005-2009 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*
* Code partly taken from (X)FST:
@@ -77,9 +77,6 @@
#define OLD_VST_SDK
#define VstInt32 long int
#define VstIntPtr long int
struct ERect
{
short top;
@@ -228,8 +225,8 @@ private:
} ;
// callback used by plugin for being able to communicate with it's host
static VstIntPtr hostCallback( AEffect * _effect, VstInt32 _opcode,
VstInt32 _index, VstIntPtr _value,
static intptr_t hostCallback( AEffect * _effect, int32_t _opcode,
int32_t _index, intptr_t _value,
void * _ptr, float _opt );
@@ -481,8 +478,7 @@ void RemoteVstPlugin::initEditor()
#ifdef LMMS_BUILD_LINUX
m_window = CreateWindowEx( 0, "LVSL", m_shortName.c_str(),
( WS_OVERLAPPEDWINDOW | WS_THICKFRAME ) &
~WS_MAXIMIZEBOX,
( WS_OVERLAPPEDWINDOW | WS_THICKFRAME ) & ~WS_MAXIMIZEBOX,
0, 0, 10, 10, NULL, NULL, hInst, NULL );
#else
@@ -528,6 +524,11 @@ bool RemoteVstPlugin::load( const std::string & _plugin_file )
{
if( ( m_libInst = LoadLibrary( _plugin_file.c_str() ) ) == NULL )
{
// give VstPlugin class a chance to start 32 bit version of RemoteVstPlugin
if( GetLastError() == ERROR_BAD_EXE_FORMAT )
{
sendMessage( IdVstBadDllFormat );
}
return false;
}
@@ -882,8 +883,8 @@ void RemoteVstPlugin::updateInOutCount()
* - audioMasterGetDirectory: return either VST-plugin-dir or LMMS-workingdir
* - audioMasterOpenFileSelector: show QFileDialog?
*/
VstIntPtr RemoteVstPlugin::hostCallback( AEffect * _effect, VstInt32 _opcode,
VstInt32 _index, VstIntPtr _value,
intptr_t RemoteVstPlugin::hostCallback( AEffect * _effect, int32_t _opcode,
int32_t _index, intptr_t _value,
void * _ptr, float _opt )
{
static VstTimeInfo _timeInfo;
@@ -911,21 +912,21 @@ VstIntPtr RemoteVstPlugin::hostCallback( AEffect * _effect, VstInt32 _opcode,
SHOW_CALLBACK( "amc: audioMasterVersion\n" );
return 2300;
case audioMasterCurrentId:
case audioMasterCurrentId:
SHOW_CALLBACK( "amc: audioMasterCurrentId\n" );
// returns the unique id of a plug that's currently
// loading
return 0;
case audioMasterIdle:
SHOW_CALLBACK ("amc: audioMasterIdle\n" );
// call application idle routine (this will
// call effEditIdle for all open editors too)
// call effEditIdle for all open editors too)
PostThreadMessage( __GuiThreadID,
WM_USER, GiveIdle, 0 );
return 0;
case audioMasterPinConnected:
case audioMasterPinConnected:
SHOW_CALLBACK( "amc: audioMasterPinConnected\n" );
// inquire if an input or output is beeing connected;
// index enumerates input or output counting from zero:
@@ -989,7 +990,7 @@ VstIntPtr RemoteVstPlugin::hostCallback( AEffect * _effect, VstInt32 _opcode,
"Parameters\n" );
return 5000;
case audioMasterGetParameterQuantization:
case audioMasterGetParameterQuantization:
SHOW_CALLBACK( "amc: audioMasterGetParameter\n"
"Quantization\n" );
// returns the integer value for +1.0 representation,
@@ -1044,7 +1045,7 @@ VstIntPtr RemoteVstPlugin::hostCallback( AEffect * _effect, VstInt32 _opcode,
// TODO
// returns platform specific ptr
return 0;
case audioMasterCloseWindow:
SHOW_CALLBACK( "amc: audioMasterCloseWindow\n" );
// TODO
@@ -1156,7 +1157,7 @@ VstIntPtr RemoteVstPlugin::hostCallback( AEffect * _effect, VstInt32 _opcode,
SHOW_CALLBACK( "amc: audioMasterVendorSpecific\n" );
// no definition, vendor specific handling
return 0;
case audioMasterCanDo:
SHOW_CALLBACK( "amc: audioMasterCanDo\n" );
return !strcmp( (char *) _ptr, "sendVstEvents" ) ||
@@ -1173,7 +1174,7 @@ VstIntPtr RemoteVstPlugin::hostCallback( AEffect * _effect, VstInt32 _opcode,
SHOW_CALLBACK( "amc: audioMasterGetDirectory\n" );
// get plug directory, FSSpec on MAC, else char*
return 0;
case audioMasterUpdateDisplay:
SHOW_CALLBACK( "amc: audioMasterUpdateDisplay\n" );
// something has changed, update 'multi-fx' display
@@ -1184,7 +1185,7 @@ VstIntPtr RemoteVstPlugin::hostCallback( AEffect * _effect, VstInt32 _opcode,
#if kVstVersion > 2
case audioMasterBeginEdit:
SHOW_CALLBACK( "amc: audioMasterBeginEdit\n" );
// begin of automation session (when mouse down),
// begin of automation session (when mouse down),
// parameter index in <index>
return 0;

View File

@@ -78,10 +78,11 @@ public:
VstPlugin::VstPlugin( const QString & _plugin ) :
QObject(),
JournallingObject(),
RemotePlugin( "remote_vst_plugin", false ),
RemotePlugin(),
m_plugin( _plugin ),
m_pluginWidget( NULL ),
m_pluginWindowID( 0 ),
m_badDllFormat( false ),
m_name(),
m_version( 0 ),
m_vendorString(),
@@ -89,6 +90,37 @@ VstPlugin::VstPlugin( const QString & _plugin ) :
{
setSplittedChannels( true );
tryLoad( "RemoteVstPlugin" );
#ifdef LMMS_BUILD_WIN64
if( m_badDllFormat )
{
m_badDllFormat = false;
tryLoad( "32/RemoteVstPlugin32" );
}
#endif
setTempo( engine::getSong()->getTempo() );
connect( engine::getSong(), SIGNAL( tempoChanged( bpm_t ) ),
this, SLOT( setTempo( bpm_t ) ) );
connect( engine::getMixer(), SIGNAL( sampleRateChanged() ),
this, SLOT( updateSampleRate() ) );
}
VstPlugin::~VstPlugin()
{
}
void VstPlugin::tryLoad( const QString &remoteVstPluginExecutable )
{
init( remoteVstPluginExecutable, false );
lock();
#ifdef LMMS_BUILD_WIN32
QWidget * helper = new QWidget;
@@ -138,7 +170,7 @@ VstPlugin::VstPlugin( const QString & _plugin ) :
unlock();
#ifdef LMMS_BUILD_WIN32
if( m_pluginWindowID )
if( !failed() && m_pluginWindowID )
{
target->setFixedSize( m_pluginGeometry );
vstSubWin * sw = new vstSubWin(
@@ -152,20 +184,6 @@ VstPlugin::VstPlugin( const QString & _plugin ) :
delete helper;
}
#endif
setTempo( engine::getSong()->getTempo() );
connect( engine::getSong(), SIGNAL( tempoChanged( bpm_t ) ),
this, SLOT( setTempo( bpm_t ) ) );
connect( engine::getMixer(), SIGNAL( sampleRateChanged() ),
this, SLOT( updateSampleRate() ) );
}
VstPlugin::~VstPlugin()
{
}
@@ -355,6 +373,10 @@ bool VstPlugin::processMessage( const message & _m )
{
switch( _m.id )
{
case IdVstBadDllFormat:
m_badDllFormat = true;
break;
case IdVstPluginWindowID:
m_pluginWindowID = _m.getInt();
break;

View File

@@ -43,6 +43,8 @@ public:
VstPlugin( const QString & _plugin );
virtual ~VstPlugin();
void tryLoad( const QString &remoteVstPluginExecutable );
virtual bool processMessage( const message & _m );
inline bool hasEditor() const
@@ -112,6 +114,8 @@ private:
int m_pluginWindowID;
QSize m_pluginGeometry;
bool m_badDllFormat;
QString m_name;
Sint32 m_version;
QString m_vendorString;

View File

@@ -0,0 +1,14 @@
INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR} ${CMAKE_SOURCE_DIR}/include)
SET(CMAKE_CXX_COMPILER "${CMAKE_CXX_COMPILER32}")
ADD_EXECUTABLE(RemoteVstPlugin32 ${CMAKE_CURRENT_SOURCE_DIR}/../RemoteVstPlugin.cpp)
ADD_CUSTOM_COMMAND(TARGET RemoteVstPlugin32 POST_BUILD COMMAND ${STRIP} ${CMAKE_CURRENT_BINARY_DIR}/RemoteVstPlugin32.exe)
INSTALL(TARGETS RemoteVstPlugin32 RUNTIME DESTINATION ${PLUGIN_DIR}/32)
INSTALL(FILES
${MINGW_PREFIX32}/bin/QtCore4.dll
${MINGW_PREFIX32}/bin/zlib1.dll
DESTINATION ${PLUGIN_DIR}/32)

View File

@@ -2,7 +2,7 @@
* communication.h - header file defining stuff concerning communication between
* LVSL-server and -client
*
* Copyright (c) 2005-2008 Tobias Doerffel <tobydox/at/users.sourceforge.net>
* Copyright (c) 2005-2010 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*
@@ -67,6 +67,7 @@ enum VstRemoteMessageIDs
// remoteVstPlugin -> vstPlugin
IdVstFailedLoadingPlugin,
IdVstBadDllFormat,
IdVstPluginWindowID,
IdVstPluginEditorGeometry,
IdVstPluginName,

View File

@@ -69,8 +69,9 @@ Plugin::Descriptor PLUGIN_EXPORT zynaddsubfx_plugin_descriptor =
ZynAddSubFxRemotePlugin::ZynAddSubFxRemotePlugin() :
QObject(),
RemotePlugin( "RemoteZynAddSubFx", false )
RemotePlugin()
{
init( "RemoteZynAddSubFx", false );
}

View File

@@ -1,7 +1,7 @@
/*
* RemotePlugin.cpp - base class providing RPC like mechanisms
*
* Copyright (c) 2008-2009 Tobias Doerffel <tobydox/at/users.sourceforge.net>
* Copyright (c) 2008-2010 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*
@@ -68,10 +68,10 @@ void ProcessWatcher::run()
RemotePlugin::RemotePlugin( const QString & _plugin_executable,
bool _wait_for_init_done ) :
RemotePlugin::RemotePlugin() :
RemotePluginBase( new shmFifo(), new shmFifo() ),
m_failed( true ),
m_process(),
m_watcher( this ),
m_commMutex( QMutex::Recursive ),
m_splitChannels( false ),
@@ -85,29 +85,6 @@ RemotePlugin::RemotePlugin( const QString & _plugin_executable,
m_inputCount( DEFAULT_CHANNELS ),
m_outputCount( DEFAULT_CHANNELS )
{
lock();
QString exec = configManager::inst()->pluginDir() +
QDir::separator() + _plugin_executable;
QStringList args;
// swap in and out for bidirectional communication
args << QString::number( out()->shmKey() );
args << QString::number( in()->shmKey() );
m_process.setProcessChannelMode( QProcess::MergedChannels );
#ifndef DEBUG_REMOTE_PLUGIN
m_process.start( exec, args );
m_watcher.start( QThread::LowestPriority );
#else
qDebug() << exec << args;
#endif
resizeSharedProcessingMemory();
if( _wait_for_init_done )
{
waitForInitDone();
}
unlock();
}
@@ -144,6 +121,43 @@ RemotePlugin::~RemotePlugin()
bool RemotePlugin::init( const QString &pluginExecutable,
bool waitForInitDoneMsg )
{
lock();
if( m_failed )
{
reset( new shmFifo(), new shmFifo() );
m_failed = false;
}
QString exec = configManager::inst()->pluginDir() +
QDir::separator() + pluginExecutable;
QStringList args;
// swap in and out for bidirectional communication
args << QString::number( out()->shmKey() );
args << QString::number( in()->shmKey() );
#ifndef DEBUG_REMOTE_PLUGIN
m_process.setProcessChannelMode( QProcess::ForwardedChannels );
m_process.start( exec, args );
m_watcher.start( QThread::LowestPriority );
#else
qDebug() << exec << args;
#endif
resizeSharedProcessingMemory();
if( waitForInitDoneMsg )
{
waitForInitDone();
}
unlock();
return failed();
}
bool RemotePlugin::process( const sampleFrame * _in_buf,
sampleFrame * _out_buf )