diff --git a/CMakeLists.txt b/CMakeLists.txt index f70493063..55d2dac40 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -258,7 +258,7 @@ ENDIF(WANT_SF2) # check for WINE -if(WANT_VST) +IF(WANT_VST) INCLUDE(CheckLibraryExists) INCLUDE(CheckIncludeFileCXX) SET(CMAKE_REQUIRED_FLAGS_ORIG ${CMAKE_REQUIRED_FLAGS}) @@ -276,11 +276,15 @@ if(WANT_VST) SET(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES_ORIG}) IF(HAVE_LIBWINE AND HAVE_WINDOWS_H) SET(LMMS_HAVE_VST TRUE) - SET(STATUS_WINE "OK") + SET(STATUS_VST "OK") ELSE(HAVE_LIBWINE AND HAVE_WINDOWS_H) - SET(STATUS_WINE "not found, please install (lib)wine-dev (or similiar) - 64 bit systems additionally need gcc-multilib and g++-multilib") + SET(STATUS_VST "not found, please install (lib)wine-dev (or similiar) - 64 bit systems additionally need gcc-multilib and g++-multilib") ENDIF(HAVE_LIBWINE AND HAVE_WINDOWS_H) ENDIF(WANT_VST) +IF(LMMS_BUILD_WIN32) + SET(LMMS_HAVE_VST TRUE) + SET(STATUS_VST "OK") +ENDIF(LMMS_BUILD_WIN32) # check for libsamplerate @@ -515,8 +519,8 @@ MESSAGE( "----------------\n" "* SoundFont2 player : ${STATUS_FLUIDSYNTH}\n" "* Stk Mallets : ${STATUS_STK}\n" -"* VST-instrument hoster : ${STATUS_WINE}\n" -"* VST-effect hoster : ${STATUS_WINE}\n" +"* VST-instrument hoster : ${STATUS_VST}\n" +"* VST-effect hoster : ${STATUS_VST}\n" "* SpectrumAnalyzer : ${STATUS_FFTW3F}\n" "* CAPS LADSPA plugins : ${STATUS_CAPS}\n" "* TAP LADSPA plugins : ${STATUS_TAP}\n" diff --git a/ChangeLog b/ChangeLog index 85f08b2c2..bf594ff13 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2008-09-04 Tobias Doerffel + + * plugins/vst_base/vst_plugin.h: + * plugins/vst_base/remote_vst_plugin.cpp: + * plugins/vst_base/communication.h: + * plugins/vst_base/vst_plugin.cpp: + * plugins/vst_base/CMakeLists.txt: + * include/text_float.h: + * include/remote_plugin.h: + * CMakeLists.txt: + made VST support layer work on native win32 + 2008-09-03 Tobias Doerffel * plugins/vst_base/communication.h: diff --git a/include/remote_plugin.h b/include/remote_plugin.h index bf5a9933f..b8a26e5f0 100755 --- a/include/remote_plugin.h +++ b/include/remote_plugin.h @@ -40,6 +40,8 @@ #include #endif +#include + #if QT_VERSION >= 0x040400 #include #include diff --git a/include/text_float.h b/include/text_float.h index 525ac3918..191daaf04 100644 --- a/include/text_float.h +++ b/include/text_float.h @@ -29,8 +29,10 @@ #include #include +#include "export.h" -class textFloat : public QWidget + +class EXPORT textFloat : public QWidget { public: textFloat( void ); diff --git a/plugins/vst_base/CMakeLists.txt b/plugins/vst_base/CMakeLists.txt index 4a6d25edc..8d69c5b73 100644 --- a/plugins/vst_base/CMakeLists.txt +++ b/plugins/vst_base/CMakeLists.txt @@ -4,6 +4,18 @@ INCLUDE(BuildPlugin) BUILD_PLUGIN(vstbase vst_base.cpp vst_plugin.cpp vst_plugin.h communication.h MOCFILES vst_plugin.h) + +IF(LMMS_BUILD_WIN32) + +ADD_DEFINITIONS(-DPTW32_STATIC_LIB) +LINK_LIBRARIES(-lQtCore4 -lpthread -lgdi32 -lwsock32) +ADD_EXECUTABLE(remote_vst_plugin ${CMAKE_CURRENT_SOURCE_DIR}/remote_vst_plugin.cpp) + +ENDIF(LMMS_BUILD_WIN32) + + +IF(LMMS_BUILD_LINUX) + IF(LMMS_HOST_X86_64) SET(EXTRA_FLAGS -m32 -Wb,--as-cmd='as --32',--ld-cmd='ld -melf_i386' -L/usr/lib32) ENDIF(LMMS_HOST_X86_64) @@ -19,4 +31,7 @@ SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES remote_vst_plugi INSTALL(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/remote_vst_plugin ${CMAKE_CURRENT_BINARY_DIR}/remote_vst_plugin.exe.so DESTINATION ${PLUGIN_DIR}) +ENDIF(LMMS_BUILD_LINUX) + + ENDIF(LMMS_HAVE_VST) diff --git a/plugins/vst_base/communication.h b/plugins/vst_base/communication.h index a299798e6..e5f742abb 100644 --- a/plugins/vst_base/communication.h +++ b/plugins/vst_base/communication.h @@ -55,6 +55,7 @@ enum VstRemoteMessageIDs { // vstPlugin -> remoteVstPlugin IdVstLoadPlugin = IdUserBase, + IdVstPluginWindowInformation, IdVstClosePlugin, IdVstSetTempo, IdVstSetLanguage, diff --git a/plugins/vst_base/remote_vst_plugin.cpp b/plugins/vst_base/remote_vst_plugin.cpp index 10a900dcf..74251547a 100644 --- a/plugins/vst_base/remote_vst_plugin.cpp +++ b/plugins/vst_base/remote_vst_plugin.cpp @@ -38,13 +38,22 @@ #include #endif +#ifdef LMMS_BUILD_LINUX + #ifdef LMMS_HAVE_SCHED_H #include #endif +#include + +#endif #include -#include + +#ifdef LMMS_BUILD_WIN32 +#include + +#endif #include @@ -76,6 +85,7 @@ struct ERect #include "communication.h" +#if 0 #ifdef LMMS_HAVE_TLS static __thread int ejmpbuf_valid = false; static __thread jmp_buf ejmpbuf; @@ -83,6 +93,7 @@ static __thread jmp_buf ejmpbuf; static pthread_key_t ejmpbuf_valid_key; static pthread_key_t ejmpbuf_key; #endif +#endif static VstHostLanguages hlang = LanguageEnglish; @@ -105,15 +116,6 @@ public: void init( const std::string & _plugin_file ); - void showEditor( void ) - { - if( m_window != NULL ) - { - PostThreadMessageA( m_guiThreadID, WM_USER, ShowEditor, - 0 ); - } - } - virtual bool process( const sampleFrame * _in, sampleFrame * _out ); @@ -190,9 +192,9 @@ public: private: - enum guiThreadMessages + enum GuiThreadMessages { - None, ShowEditor, ClosePlugin + None, ClosePlugin } ; // callback used by plugin for being able to communicate with it's host @@ -252,6 +254,8 @@ remoteVstPlugin::remoteVstPlugin( key_t _shm_in, key_t _shm_out ) : m_bpm( 0 ), m_currentSamplePos( 0 ) { + pthread_mutex_init( &m_lock, NULL ); + pthread_cond_init( &m_windowStatusChange, NULL ); } @@ -266,9 +270,12 @@ remoteVstPlugin::~remoteVstPlugin() { //lvsMessage( "could not post message to gui thread" ); } + pthread_mutex_lock( &m_lock ); pthread_cond_wait( &m_windowStatusChange, &m_lock ); m_plugin->dispatcher( m_plugin, effEditClose, 0, 0, NULL, 0.0 ); +#ifdef LMMS_BUILD_LINUX CloseWindow( m_window ); +#endif m_window = NULL; } @@ -280,6 +287,9 @@ remoteVstPlugin::~remoteVstPlugin() delete[] m_inputs; delete[] m_outputs; + + pthread_mutex_destroy( &m_lock ); + pthread_cond_destroy( &m_windowStatusChange ); } @@ -293,9 +303,15 @@ bool remoteVstPlugin::processMessage( const message & _m ) init( _m.getString() ); break; - case IdShowUI: - showEditor(); +#ifdef LMMS_BUILD_WIN32 + case IdVstPluginWindowInformation: + { + HWND top = FindWindowEx( NULL, NULL, NULL, + _m.getString().c_str() ); + m_window = FindWindowEx( top, NULL, NULL, NULL ); break; + } +#endif case IdVstSetTempo: setBPM( _m.getInt() ); @@ -350,18 +366,16 @@ void remoteVstPlugin::init( const std::string & _plugin_file ) fprintf( stderr, "could not create GUI-thread\n" ); return; } - pthread_cond_wait( &m_windowStatusChange, &m_lock); + pthread_mutex_lock( &m_lock ); + pthread_cond_wait( &m_windowStatusChange, &m_lock ); // now post some information about our plugin sendMessage( message( IdVstPluginWindowID ).addInt( m_windowID ) ); - if( m_windowID != 0 ) - { - sendMessage( message( IdVstPluginEditorGeometry ). + sendMessage( message( IdVstPluginEditorGeometry ). addInt( m_windowWidth ). addInt( m_windowHeight ) ); - } sendMessage( message( IdVstPluginName ).addString( pluginName() ) ); sendMessage( message( IdVstPluginVersion ).addInt( pluginVersion() ) ); @@ -480,9 +494,6 @@ bool remoteVstPlugin::process( const sampleFrame * _in, sampleFrame * _out ) m_currentSamplePos += bufferSize(); - // give plugin some idle-time for GUI-update and so on... - m_plugin->dispatcher( m_plugin, effEditIdle, 0, 0, NULL, 0 ); - } @@ -984,6 +995,7 @@ DWORD WINAPI remoteVstPlugin::guiEventLoop( LPVOID _param ) remoteVstPlugin * _this = static_cast( _param ); _this->m_guiThreadID = GetCurrentThreadId(); +#if 0 // "guard point" to trap errors that occur during plugin loading #ifdef LMMS_HAVE_TLS if( sigsetjmp( ejmpbuf, 1 ) ) @@ -1005,12 +1017,17 @@ DWORD WINAPI remoteVstPlugin::guiEventLoop( LPVOID _param ) pthread_key_create( &ejmpbuf_valid_key, NULL ); pthread_setspecific( ejmpbuf_valid_key, ejmpbuf_valid ); +#ifdef LMMS_BUILD_WIN32 + if( setjmp( *ejmpbuf ) ) +#else if( sigsetjmp( *ejmpbuf, 1 ) ) +#endif { exit( 1 ); } *ejmpbuf_valid = true; +#endif #endif // Note: m_lock is held while this function is called @@ -1029,21 +1046,27 @@ DWORD WINAPI remoteVstPlugin::guiEventLoop( LPVOID _param ) return( 1 ); } +#ifdef LMMS_BUILD_LINUX if( ( _this->m_window = CreateWindowExA( 0, "LVSL", _this->m_shortName.c_str(), - ( WS_OVERLAPPEDWINDOW & ~WS_THICKFRAME & + ( WS_OVERLAPPEDWINDOW | WS_THICKFRAME & ~WS_MAXIMIZEBOX ), - 0, 0, 1, 1, NULL, NULL, hInst, NULL ) ) == NULL ) + 0, 0, 10, 10, + NULL, NULL, hInst, NULL ) ) == NULL ) { fprintf( stderr, "cannot create editor window\n" ); pthread_cond_signal( &_this->m_windowStatusChange ); return( 1 ); } - ShowWindow( _this->m_window, SW_SHOWMINIMIZED ); - ShowWindow( _this->m_window, SW_HIDE ); + + ShowWindow( _this->m_window, SW_SHOWNORMAL ); _this->m_windowID = (Sint32) GetPropA( _this->m_window, "__wine_x11_whole_window" ); +#else + _this->m_windowID = 1; // arbitrary value on win32 to signal + // vstPlugin-class that we have an editor +#endif _this->m_plugin->dispatcher( _this->m_plugin, effEditOpen, 0, 0, @@ -1055,23 +1078,28 @@ DWORD WINAPI remoteVstPlugin::guiEventLoop( LPVOID _param ) _this->m_windowWidth = er->right - er->left; _this->m_windowHeight = er->bottom - er->top; - + SetWindowPos( _this->m_window, 0, 0, 0, _this->m_windowWidth + 8, - _this->m_windowHeight + 26, 0 + _this->m_windowHeight + 26, SWP_SHOWWINDOW ); + + UpdateWindow( _this->m_window ); + #if 0 - SWP_NOACTIVATE /*| SWP_NOREDRAW*/ | SWP_NOMOVE | - SWP_NOOWNERZORDER | SWP_NOZORDER -#endif - ); #ifdef LMMS_HAVE_TLS ejmpbuf_valid = false; #else *ejmpbuf_valid = false; +#endif #endif pthread_cond_signal( &_this->m_windowStatusChange ); + HWND timer_window = CreateWindowEx( 0, "LVSL", "dummy", + 0, 0, 0, 0, 0, NULL, NULL, hInst, NULL ); + // install GUI update timer + SetTimer( timer_window, 1000, 50, NULL ); + MSG msg; bool quit = false; @@ -1080,16 +1108,17 @@ DWORD WINAPI remoteVstPlugin::guiEventLoop( LPVOID _param ) TranslateMessage( &msg ); DispatchMessageA( &msg ); - if( msg.message == WM_USER ) + if( msg.message == WM_TIMER ) + { + // give plugin some idle-time for GUI-update + _this->m_plugin->dispatcher( _this->m_plugin, + effEditIdle, 0, 0, + NULL, 0 ); + } + else if( msg.message == WM_USER ) { switch( msg.wParam ) { - case ShowEditor: - ShowWindow( _this->m_window, - SW_SHOWNORMAL ); - UpdateWindow( _this->m_window ); - break; - case ClosePlugin: quit = true; break; @@ -1108,7 +1137,7 @@ DWORD WINAPI remoteVstPlugin::guiEventLoop( LPVOID _param ) -int main( int _argc, char * * _argv ) +int main( int _argc, char * * _argv ) { if( _argc < 3 ) { @@ -1147,6 +1176,7 @@ int main( int _argc, char * * _argv ) return( -1 ); } +#ifdef LMMS_BUILD_LINUX #ifdef LMMS_HAVE_SCHED_H // try to set realtime-priority struct sched_param sparam; @@ -1157,6 +1187,7 @@ int main( int _argc, char * * _argv ) fprintf( stderr, "could not set realtime priority for " "remoteVstPlugin\n" ); } +#endif #endif __plugin = new remoteVstPlugin( atoi( _argv[1] ), atoi( _argv[2] ) ); diff --git a/plugins/vst_base/vst_plugin.cpp b/plugins/vst_base/vst_plugin.cpp index 85a7c0a84..b7fd95751 100644 --- a/plugins/vst_base/vst_plugin.cpp +++ b/plugins/vst_base/vst_plugin.cpp @@ -30,11 +30,20 @@ #include #include #include +#ifdef LMMS_BUILD_LINUX #include #include +#else +#include +#endif #include +#ifdef LMMS_BUILD_WIN32 +#include +#endif + + #include "config_mgr.h" #include "engine.h" #include "main_window.h" @@ -42,7 +51,6 @@ - vstPlugin::vstPlugin( const QString & _plugin ) : QObject(), journallingObject(), @@ -58,6 +66,26 @@ vstPlugin::vstPlugin( const QString & _plugin ) : setSplittedChannels( true ); lock(); +#ifdef LMMS_BUILD_WIN32 + QWidget * helper = new QWidget; + QWidget * target = new QWidget( helper ); + QHBoxLayout * l = new QHBoxLayout; + l->setMargin( 0 ); + l->addWidget( target ); + helper->setLayout( l ); + + static int k = 0; + const QString t = QString( "vst%1%2" ).arg( GetCurrentProcessId()<<10 ). + arg( ++k ); + helper->setWindowTitle( t ); + + // we've to call that for making sure, Qt created the windows + (void) helper->winId(); + (void) target->winId(); + + sendMessage( message( IdVstPluginWindowInformation ). + addString( t.toStdString() ) ); +#endif VstHostLanguages hlang = LanguageEnglish; switch( QLocale::system().language() ) @@ -83,6 +111,21 @@ vstPlugin::vstPlugin( const QString & _plugin ) : waitForInitDone(); unlock(); + +#ifdef LMMS_BUILD_WIN32 + if( m_pluginWindowID ) + { + target->setFixedSize( m_pluginGeometry ); + engine::getMainWindow()->workspace()->addSubWindow( helper ) + ->setAttribute( Qt::WA_DeleteOnClose, FALSE ); + helper->setWindowTitle( name() ); + m_pluginWidget = helper; + } + else + { + delete helper; + } +#endif } @@ -112,7 +155,7 @@ QWidget * vstPlugin::showEditor( QWidget * _parent ) } return( m_pluginWidget ); } - +#ifdef LMMS_BUILD_LINUX if( m_pluginWindowID == 0 ) { return( NULL ); @@ -128,7 +171,6 @@ QWidget * vstPlugin::showEditor( QWidget * _parent ) ->setAttribute( Qt::WA_DeleteOnClose, FALSE ); } -#ifdef LMMS_BUILD_LINUX QX11EmbedContainer * xe = new QX11EmbedContainer( m_pluginWidget ); xe->embedClient( m_pluginWindowID ); xe->setFixedSize( m_pluginGeometry ); @@ -148,6 +190,9 @@ QWidget * vstPlugin::showEditor( QWidget * _parent ) void vstPlugin::hideEditor( void ) { + if( m_pluginWidget ) + m_pluginWidget->hide(); + return; if( m_pluginWidget != NULL && m_pluginWidget->parentWidget() ) { m_pluginWidget->parentWidget()->hide(); @@ -275,7 +320,7 @@ bool vstPlugin::processMessage( const message & _m ) const int w = _m.getInt( 0 ); const int h = _m.getInt( 1 ); m_pluginGeometry = QSize( w, h ); - if( m_pluginWidget != NULL ) +/* if( m_pluginWidget != NULL ) { m_pluginWidget->setFixedSize( m_pluginGeometry ); @@ -285,7 +330,7 @@ bool vstPlugin::processMessage( const message & _m ) )->setFixedSize( m_pluginGeometry ); } - } + }*/ break; } diff --git a/plugins/vst_base/vst_plugin.h b/plugins/vst_base/vst_plugin.h index f87d749c4..33c12149f 100644 --- a/plugins/vst_base/vst_plugin.h +++ b/plugins/vst_base/vst_plugin.h @@ -37,7 +37,8 @@ -class vstPlugin : public QObject, public journallingObject, public remotePlugin +class PLUGIN_EXPORT vstPlugin : public QObject, public journallingObject, + public remotePlugin { Q_OBJECT public: