From f5be314b621281286b27a3635ec55dd2bbce4eaf Mon Sep 17 00:00:00 2001 From: akimaze Date: Sun, 6 Jun 2021 14:05:44 +0200 Subject: [PATCH 01/23] First attempt to load native linux vst in vestige. --- include/aeffectx.h | 4 + plugins/vestige/vestige.cpp | 1 + plugins/vst_base/CMakeLists.txt | 5 + .../NativeLinuxRemoteVstPlugin64.cmake | 13 + plugins/vst_base/RemoteVstPlugin.cpp | 327 ++++++++++++++++-- .../vst_base/RemoteVstPlugin/CMakeLists.txt | 20 +- plugins/vst_base/VstPlugin.cpp | 22 +- plugins/vst_base/vstbase/CMakeLists.txt | 1 + 8 files changed, 356 insertions(+), 37 deletions(-) create mode 100644 plugins/vst_base/NativeLinuxRemoteVstPlugin64.cmake diff --git a/include/aeffectx.h b/include/aeffectx.h index b7a78dfad2b..06503ce5bee 100644 --- a/include/aeffectx.h +++ b/include/aeffectx.h @@ -29,7 +29,11 @@ #include // Calling convention +#ifndef NATIVE_LINUX_VST #define VST_CALL_CONV __cdecl +#else +#define VST_CALL_CONV +#endif #define CCONST(a, b, c, d)( ( ( (int32_t) a ) << 24 ) | \ ( ( (int32_t) b ) << 16 ) | \ diff --git a/plugins/vestige/vestige.cpp b/plugins/vestige/vestige.cpp index d76ac37f6e5..2d33ec961d2 100644 --- a/plugins/vestige/vestige.cpp +++ b/plugins/vestige/vestige.cpp @@ -682,6 +682,7 @@ void VestigeInstrumentView::openPlugin() QStringList types; types << tr( "DLL-files (*.dll)" ) << tr( "EXE-files (*.exe)" ) + << tr( "SO-files (*.so)" ) ; ofd.setNameFilters( types ); diff --git a/plugins/vst_base/CMakeLists.txt b/plugins/vst_base/CMakeLists.txt index 873ed5f8e81..30ac329bf21 100644 --- a/plugins/vst_base/CMakeLists.txt +++ b/plugins/vst_base/CMakeLists.txt @@ -8,6 +8,7 @@ INCLUDE(ExternalProject) # These variables are not meant to be used normally, except packaging SET(REMOTE_VST_PLUGIN_FILEPATH_32 "32/RemoteVstPlugin32" CACHE STRING "Relative file path to RemoteVstPlugin32") SET(REMOTE_VST_PLUGIN_FILEPATH_64 "RemoteVstPlugin64" CACHE STRING "Relative file path to RemoteVstPlugin64") +SET(NATIVE_LINUX_REMOTE_VST_PLUGIN_FILEPATH_64 "NativeLinuxRemoteVstPlugin64" CACHE STRING "Relative file path to NativeLinuxRemoteVstPlugin64") ADD_SUBDIRECTORY(vstbase) @@ -48,3 +49,7 @@ ENDIF() IF(WANT_VST_64) INCLUDE("${CMAKE_CURRENT_LIST_DIR}/RemoteVstPlugin64.cmake") ENDIF() + +if(LMMS_BUILD_LINUX) +INCLUDE("${CMAKE_CURRENT_LIST_DIR}/NativeLinuxRemoteVstPlugin64.cmake") +ENDIF() diff --git a/plugins/vst_base/NativeLinuxRemoteVstPlugin64.cmake b/plugins/vst_base/NativeLinuxRemoteVstPlugin64.cmake new file mode 100644 index 00000000000..e04a030b23f --- /dev/null +++ b/plugins/vst_base/NativeLinuxRemoteVstPlugin64.cmake @@ -0,0 +1,13 @@ +IF(LMMS_BUILD_WIN64) + RETURN() +ELSEIF(LMMS_BUILD_LINUX) + ExternalProject_Add(NativeLinuxRemoteVstPlugin64 + "${EXTERNALPROJECT_ARGS}" + CMAKE_ARGS + "${EXTERNALPROJECT_CMAKE_ARGS}" + "-DCMAKE_CXX_FLAGS=-m64 -DNATIVE_LINUX_VST" + "-DCMAKE_C_FLAGS=-DNATIVE_LINUX_VST" + ) + INSTALL(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/../NativeLinuxRemoteVstPlugin64" "${CMAKE_CURRENT_BINARY_DIR}/../NativeLinuxRemoteVstPlugin64.so" DESTINATION "${PLUGIN_DIR}") +ENDIF() + diff --git a/plugins/vst_base/RemoteVstPlugin.cpp b/plugins/vst_base/RemoteVstPlugin.cpp index 942c9e960c2..c0bb1e72017 100644 --- a/plugins/vst_base/RemoteVstPlugin.cpp +++ b/plugins/vst_base/RemoteVstPlugin.cpp @@ -52,12 +52,38 @@ #include #endif +#ifndef NATIVE_LINUX_VST #include +#endif #endif #define USE_WS_PREFIX +#ifndef NATIVE_LINUX_VST #include +#else +#include +#include +#include +#include +#include +#include +#include +#include + +// https://stackoverflow.com/questions/22476110/c-compiling-error-including-x11-x-h-x11-xlib-h +#undef Bool +#undef CursorShape +#undef Expose +#undef KeyPress +#undef KeyRelease +#undef FocusIn +#undef FocusOut +#undef FontChange +#undef None +#undef Status +#undef Unsorte +#endif #ifdef USE_MINGW_THREADS_REPLACEMENT # include @@ -122,10 +148,14 @@ class RemoteVstPlugin; RemoteVstPlugin * __plugin = NULL; +#ifndef NATIVE_LINUX_VST HWND __MessageHwnd = NULL; DWORD __processingThreadId = 0; +#else +pthread_t __processingThreadId = 0; +#endif - +#ifndef NATIVE_LINUX_VST //Returns the last Win32 error, in string format. Returns an empty string if there is no error. std::string GetErrorAsString(DWORD errorMessageID) { @@ -144,7 +174,7 @@ std::string GetErrorAsString(DWORD errorMessageID) return message; } - +#endif class RemoteVstPlugin : public RemotePluginClient { @@ -333,13 +363,26 @@ class RemoteVstPlugin : public RemotePluginClient void idle(); void processUIThreadMessages(); + void sendX11Idle(); +#ifndef NATIVE_LINUX_VST static DWORD WINAPI processingThread( LPVOID _param ); +#else + static void * processingThread2( void * _param ); +#endif + static bool setupMessageWindow(); + +#ifndef NATIVE_LINUX_VST static DWORD WINAPI guiEventLoop(); +#else + void guiEventLoop(); +#endif + +#ifndef NATIVE_LINUX_VST static LRESULT CALLBACK wndProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); - +#endif private: enum GuiThreadMessages @@ -389,10 +432,23 @@ class RemoteVstPlugin : public RemotePluginClient std::string m_shortName; +#ifndef NATIVE_LINUX_VST HINSTANCE m_libInst; +#else + void* m_libInst; +#endif AEffect * m_plugin; +#ifndef NATIVE_LINUX_VST HWND m_window; +#else + Window m_window; + Display* m_display; + Atom wmDeleteMessage; + Atom lmmsUiEvent; + Atom lmmsX11GiveIdle; + bool m_x11WindowVisible = false; +#endif intptr_t m_windowID; int m_windowWidth; int m_windowHeight; @@ -551,7 +607,11 @@ RemoteVstPlugin::~RemoteVstPlugin() if( m_libInst != NULL ) { +#ifndef NATIVE_LINUX_VST FreeLibrary( m_libInst ); +#else + dlclose( m_libInst ); +#endif m_libInst = NULL; } @@ -577,7 +637,12 @@ bool RemoteVstPlugin::processMessage( const message & _m ) return true; case IdToggleUI: + debugMessage("toogle 5"); +#ifndef NATIVE_LINUX_VST if( m_window && IsWindowVisible( m_window ) ) +#else + if (m_window && m_x11WindowVisible) +#endif { hideEditor(); } @@ -585,10 +650,16 @@ bool RemoteVstPlugin::processMessage( const message & _m ) { showEditor(); } + return true; case IdIsUIVisible: + debugMessage("is visible?"); +#ifndef NATIVE_LINUX_VST bool visible = m_window && IsWindowVisible( m_window ); +#else + bool visible = m_window && m_x11WindowVisible; +#endif sendMessage( message( IdIsUIVisible ) .addInt( visible ? 1 : 0 ) ); return true; @@ -596,8 +667,10 @@ bool RemoteVstPlugin::processMessage( const message & _m ) } else if (EMBED && _m.id == IdShowUI) { +#ifndef NATIVE_LINUX_VST ShowWindow( m_window, SW_SHOWNORMAL ); UpdateWindow( m_window ); +#endif return true; } @@ -728,8 +801,8 @@ void RemoteVstPlugin::init( const std::string & _plugin_file ) sendMessage( message( IdVstPluginEditorGeometry ). addInt( m_windowWidth ). addInt( m_windowHeight ) ); - sendMessage( message( IdVstPluginName ).addString( pluginName() ) ); + debugMessage( std::string("plugin name: ") + pluginName() + "\n" ); sendMessage( message( IdVstPluginVersion ).addInt( pluginVersion() ) ); sendMessage( message( IdVstPluginVendorString ). addString( pluginVendorString() ) ); @@ -740,6 +813,7 @@ void RemoteVstPlugin::init( const std::string & _plugin_file ) sendMessage( IdInitDone ); + debugMessage( "initialization done\n" ); m_initialized = true; } @@ -765,7 +839,7 @@ void RemoteVstPlugin::initEditor() return; } - +#ifndef NATIVE_LINUX_VST HMODULE hInst = GetModuleHandle( NULL ); if( hInst == NULL ) { @@ -812,6 +886,46 @@ void RemoteVstPlugin::initEditor() // 64-bit versions of Windows use 32-bit handles for interoperability m_windowID = (intptr_t) m_window; #endif + +#else + XEvent e; + Atom prop_atom, val_atom; + + if (m_display == NULL) + m_display = XOpenDisplay(NULL); + m_window = XCreateSimpleWindow(m_display, DefaultRootWindow(m_display), 0, 0, 400, 400, 0, 0, 0); + + wmDeleteMessage = XInternAtom(m_display, "WM_DELETE_WINDOW", false); + XSetWMProtocols(m_display, m_window, &wmDeleteMessage, 1); + lmmsUiEvent = XInternAtom(m_display, "_APP_EVT", false); + lmmsX11GiveIdle = XInternAtom(m_display, "_APP_EVT_IDLE", false); + + // make tool window + prop_atom = XInternAtom(m_display, "_NET_WM_WINDOW_TYPE", False); + val_atom = XInternAtom(m_display, "_NET_WM_WINDOW_TYPE_DIALOG", False); + XChangeProperty(m_display, m_window, prop_atom, XA_ATOM, 32, PropModeReplace, (unsigned char *)&val_atom, 1); + + // change name + XStoreName(m_display, m_window, "LVSL"); + + ERect * er; + pluginDispatch( effEditGetRect, 0, 0, &er ); + + m_windowWidth = er->right - er->left; + m_windowHeight = er->bottom - er->top; + XResizeWindow(m_display, m_window, m_windowWidth, m_windowHeight); + + XMapWindow(m_display, m_window); + XFlush(m_display); + + pluginDispatch( effEditOpen, 0, (intptr_t) m_display, (void*) m_window ); + + XSelectInput(m_display, m_window, SubstructureNotifyMask | ButtonPressMask | ButtonReleaseMask + | ButtonMotionMask | ExposureMask | KeyPressMask); + + pluginDispatch( effEditTop ); + m_x11WindowVisible = true; +#endif } @@ -820,7 +934,14 @@ void RemoteVstPlugin::initEditor() void RemoteVstPlugin::showEditor() { if( !EMBED && !HEADLESS && m_window ) { +#ifndef NATIVE_LINUX_VST ShowWindow( m_window, SW_SHOWNORMAL ); +#else + debugMessage("show editor"); + XMapWindow(m_display, m_window); + XFlush(m_display); + m_x11WindowVisible = true; +#endif } } @@ -830,7 +951,14 @@ void RemoteVstPlugin::showEditor() { void RemoteVstPlugin::hideEditor() { if( !EMBED && !HEADLESS && m_window ) { +#ifndef NATIVE_LINUX_VST ShowWindow( m_window, SW_HIDE ); +#else + debugMessage("hide editor"); + XUnmapWindow(m_display, m_window); + XFlush(m_display); + m_x11WindowVisible = false; +#endif } } @@ -839,6 +967,7 @@ void RemoteVstPlugin::hideEditor() { void RemoteVstPlugin::destroyEditor() { + debugMessage("destroy editor"); if( m_window == NULL ) { return; @@ -846,7 +975,11 @@ void RemoteVstPlugin::destroyEditor() pluginDispatch( effEditClose ); // Destroying the window takes some time in Wine 1.8.5 +#ifndef NATIVE_LINUX_VST DestroyWindow( m_window ); +#else + XCloseDisplay(m_display); +#endif m_window = NULL; } @@ -855,15 +988,24 @@ void RemoteVstPlugin::destroyEditor() bool RemoteVstPlugin::load( const std::string & _plugin_file ) { +#ifndef NATIVE_LINUX_VST if( ( m_libInst = LoadLibraryW( toWString(_plugin_file).c_str() ) ) == NULL ) { DWORD error = GetLastError(); debugMessage( "LoadLibrary failed: " + GetErrorAsString(error) ); return false; } +#else + m_libInst = dlopen(_plugin_file.c_str(), RTLD_LAZY); + if ( m_libInst == NULL) { + debugMessage( std::string("LoadLibrary failed: ") + dlerror() ); + return false; + } +#endif typedef AEffect * ( VST_CALL_CONV * mainEntryPointer ) ( audioMasterCallback ); +#ifndef NATIVE_LINUX_VST mainEntryPointer mainEntry = (mainEntryPointer) GetProcAddress( m_libInst, "VSTPluginMain" ); if( mainEntry == NULL ) @@ -876,12 +1018,20 @@ bool RemoteVstPlugin::load( const std::string & _plugin_file ) mainEntry = (mainEntryPointer) GetProcAddress( m_libInst, "main" ); } +#else + mainEntryPointer mainEntry = (mainEntryPointer) dlsym(m_libInst, "VSTPluginMain"); + if( mainEntry == NULL ) + mainEntry = (mainEntryPointer) dlsym(m_libInst, "VstPluginMain"); + if( mainEntry == NULL ) + mainEntry = (mainEntryPointer) dlsym(m_libInst, "main"); +#endif + if( mainEntry == NULL ) { debugMessage( "could not find entry point\n" ); return false; } - + m_plugin = mainEntry( hostCallback ); if( m_plugin == NULL ) { @@ -1550,7 +1700,11 @@ int RemoteVstPlugin::updateInOutCount() return 1; } +#ifndef NATIVE_LINUX_VST if( GetCurrentThreadId() == __processingThreadId ) +#else + if( pthread_equal(pthread_self(), __processingThreadId) ) +#endif { debugMessage( "Plugin requested I/O change from processing " "thread. Request denied; stability may suffer.\n" ); @@ -1643,7 +1797,11 @@ intptr_t RemoteVstPlugin::hostCallback( AEffect * _effect, int32_t _opcode, SHOW_CALLBACK ("amc: audioMasterIdle\n" ); // call application idle routine (this will // call effEditIdle for all open editors too) +#ifndef NATIVE_LINUX_VST PostMessage( __MessageHwnd, WM_USER, GiveIdle, 0 ); +#else + __plugin->sendX11Idle(); +#endif return 0; case audioMasterPinConnected: @@ -1838,6 +1996,7 @@ intptr_t RemoteVstPlugin::hostCallback( AEffect * _effect, int32_t _opcode, { return 0; } +#ifndef NATIVE_LINUX_VST __plugin->m_windowWidth = _index; __plugin->m_windowHeight = _value; HWND window = __plugin->m_window; @@ -1853,6 +2012,7 @@ intptr_t RemoteVstPlugin::hostCallback( AEffect * _effect, int32_t _opcode, message( IdVstPluginEditorGeometry ). addInt( __plugin->m_windowWidth ). addInt( __plugin->m_windowHeight ) ); +#endif return 1; } @@ -1963,7 +2123,11 @@ intptr_t RemoteVstPlugin::hostCallback( AEffect * _effect, int32_t _opcode, case audioMasterUpdateDisplay: SHOW_CALLBACK( "amc: audioMasterUpdateDisplay\n" ); // something has changed, update 'multi-fx' display +#ifndef NATIVE_LINUX_VST PostMessage( __MessageHwnd, WM_USER, GiveIdle, 0 ); +#else + __plugin->sendX11Idle(); +#endif return 0; #if kVstVersion > 2 @@ -2030,22 +2194,47 @@ void RemoteVstPlugin::processUIThreadMessages() setProcessing( false ); } +#ifdef NATIVE_LINUX_VST +void RemoteVstPlugin::sendX11Idle() +{ + if (m_window != NULL) + { + XEvent evt; + evt.xclient.type = ClientMessage; + evt.xclient.serial = 0; + evt.xclient.send_event = true; + evt.xclient.message_type = lmmsX11GiveIdle; + evt.xclient.format = 32; + evt.xclient.window = m_window; + XSendEvent(m_display, m_window, true, NoEventMask, &evt); + XFlush(m_display); + } +} +#endif - +#ifndef NATIVE_LINUX_VST DWORD WINAPI RemoteVstPlugin::processingThread( LPVOID _param ) +#else +void * RemoteVstPlugin::processingThread2(void * _param) +#endif { + #ifndef NATIVE_LINUX_VST __processingThreadId = GetCurrentThreadId(); - + #else + __processingThreadId = pthread_self(); + #endif + RemoteVstPlugin * _this = static_cast( _param ); RemotePluginClient::message m; while( ( m = _this->receiveMessage() ).id != IdQuit ) { + if( m.id == IdStartProcessing || m.id == IdMidiEvent || m.id == IdVstSetParameter - || m.id == IdVstSetTempo ) + || m.id == IdVstSetTempo) { _this->processMessage( m ); } @@ -2056,24 +2245,46 @@ DWORD WINAPI RemoteVstPlugin::processingThread( LPVOID _param ) } else { +#ifndef NATIVE_LINUX_VST PostMessage( __MessageHwnd, WM_USER, ProcessPluginMessage, (LPARAM) new message( m ) ); +#else + //_this->processMessage( m ); + + //_this->debugMessage("wysylaie"); + if (_this->m_window != NULL) + { + XEvent evt; + evt.xclient.type = ClientMessage; + evt.xclient.serial = 0; + evt.xclient.send_event = true; + evt.xclient.message_type = _this->lmmsUiEvent; + evt.xclient.format = 32; + evt.xclient.window = _this->m_window; + //evt.xclient.data.l[0] = XInternAtom(_this->m_display, "_APP_EVT_PTR", false); + uintptr_t val = uintptr_t(new message( m )); + //std::stringstream ss; + //ss << val; + //_this->debugMessage("wyslane: " + ss.str()); + //https://stackoverflow.com/questions/2810280/how-to-store-a-64-bit-integer-in-two-32-bit-integers-and-convert-back-again + //evt.xclient.data.l[0] = val; + evt.xclient.data.l[0] = (uint32_t)((val & 0xFFFFFFFF00000000LL) >> 32); + evt.xclient.data.l[1] = (uint32_t)(val & 0xFFFFFFFFLL); + //evt.xclient.data.l[0] = _this->lmmsUiEvent; + XSendEvent(_this->m_display, _this->m_window, true, NoEventMask, &evt); + XFlush(_this->m_display); + } +#endif } } - - // notify GUI thread about shutdown - PostMessage( __MessageHwnd, WM_USER, ClosePlugin, 0 ); - - return 0; } - - bool RemoteVstPlugin::setupMessageWindow() { +#ifndef NATIVE_LINUX_VST HMODULE hInst = GetModuleHandle( NULL ); if( hInst == NULL ) { @@ -2087,13 +2298,13 @@ bool RemoteVstPlugin::setupMessageWindow() hInst, NULL ); // install GUI update timer SetTimer( __MessageHwnd, 1000, 50, NULL ); - +#endif return true; } - +#ifndef NATIVE_LINUX_VST DWORD WINAPI RemoteVstPlugin::guiEventLoop() { MSG msg; @@ -2105,10 +2316,62 @@ DWORD WINAPI RemoteVstPlugin::guiEventLoop() return 0; } +#else +void RemoteVstPlugin::guiEventLoop() +{ + XEvent e; + while(true) + { + if (XQLength(m_display) > 0) { + XNextEvent(m_display, &e); + + if (e.type == ClientMessage) + { + if (m_window == NULL || e.xclient.window != m_window) + continue; + if (e.xclient.message_type == lmmsX11GiveIdle) + { + //debugMessage("idle!!!"); + if (__plugin->isInitialized()) + __plugin->idle(); + return; + } + if (e.xclient.message_type == lmmsUiEvent) + { + //debugMessage("zdarzenie!!!"); + //uintptr_t mptr = ((uintptr_t)e.xclient.data.l[0]) << 32 | e.xclient.data.l[1]; + uintptr_t mptr = ((uintptr_t)e.xclient.data.l[0] << 32); + mptr = mptr | e.xclient.data.l[1]; + //std::stringstream ss; + //ss << mptr; + //debugMessage("znalezione " +ss.str()); + message * m = (message *) mptr; + if(__plugin->isInitialized()) + __plugin->queueMessage( *m ); + delete m; + if(__plugin->isInitialized() && !__plugin->isProcessing() ) + { + __plugin->processUIThreadMessages(); + } + + } + else if (e.xclient.data.l[0] == wmDeleteMessage) + { + //m_window = NULL; + debugMessage("Hide editor"); + hideEditor(); + } + } + } + /*else + if (__plugin->isInitialized()) + __plugin->idle();*/ + } +} +#endif - - +#ifndef NATIVE_LINUX_VST LRESULT CALLBACK RemoteVstPlugin::wndProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { @@ -2155,7 +2418,7 @@ LRESULT CALLBACK RemoteVstPlugin::wndProc( HWND hwnd, UINT uMsg, return DefWindowProc( hwnd, uMsg, wParam, lParam ); } - +#endif int main( int _argc, char * * _argv ) @@ -2169,8 +2432,11 @@ int main( int _argc, char * * _argv ) fprintf( stderr, "not enough arguments\n" ); return -1; } - +#ifndef NATIVE_LINUX_VST OleInitialize(nullptr); +#else + XInitThreads(); +#endif #ifdef LMMS_BUILD_LINUX #ifdef LMMS_HAVE_SCHED_H // try to set realtime-priority @@ -2188,6 +2454,7 @@ int main( int _argc, char * * _argv ) } #endif +#ifndef NATIVE_LINUX_VST HMODULE hInst = GetModuleHandle( NULL ); if( hInst == NULL ) { @@ -2211,6 +2478,7 @@ int main( int _argc, char * * _argv ) return -1; } +#endif { #ifdef SYNC_WITH_SHM_FIFO int embedMethodIndex = 3; @@ -2265,20 +2533,27 @@ int main( int _argc, char * * _argv ) { return -1; } +#ifndef NATIVE_LINUX_VST if( CreateThread( NULL, 0, RemoteVstPlugin::processingThread, __plugin, 0, NULL ) == NULL ) +#else + int err = 0; + err = pthread_create(&__processingThreadId, NULL, &RemoteVstPlugin::processingThread2, __plugin); + if (err != 0) +#endif { __plugin->debugMessage( "could not create " "processingThread\n" ); return -1; } - RemoteVstPlugin::guiEventLoop(); + + __plugin->guiEventLoop(); } - - + delete __plugin; - +#ifndef NATIVE_LINUX_VST OleUninitialize(); +#endif return 0; } diff --git a/plugins/vst_base/RemoteVstPlugin/CMakeLists.txt b/plugins/vst_base/RemoteVstPlugin/CMakeLists.txt index aa77459b68a..e80cfe755e6 100644 --- a/plugins/vst_base/RemoteVstPlugin/CMakeLists.txt +++ b/plugins/vst_base/RemoteVstPlugin/CMakeLists.txt @@ -10,9 +10,9 @@ CHECK_CXX_DEFINE(IS_WIN "_WIN32") CHECK_CXX_DEFINE(IS_WIN64 "_WIN64") CHECK_CXX_DEFINE(IS_MINGW "__MINGW32__") -if(NOT IS_WIN) - message(FATAL_ERROR "Toolchain used does not target windows.") -ENDIF() +#if(NOT IS_WIN) +# message(FATAL_ERROR "Toolchain used does not target windows.") +#ENDIF() if(IS_WIN64 OR CMAKE_SIZEOF_VOID_P EQUAL 8) set(BITNESS 64) @@ -26,12 +26,22 @@ FOREACH( OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES} ) SET("CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG}" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}") ENDFOREACH() +if(NOT IS_WIN) +set(EXE_NAME NativeLinuxRemoteVstPlugin${BITNESS}) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/") +else() set(EXE_NAME RemoteVstPlugin${BITNESS}) +endif() add_executable(${EXE_NAME} WIN32 ../RemoteVstPlugin.cpp ) - -target_link_libraries(${EXE_NAME} ole32) +if(IS_WIN) + target_link_libraries(${EXE_NAME} ole32) +else() + target_link_libraries(${EXE_NAME} pthread) + target_link_libraries(${EXE_NAME} dl) + target_link_libraries(${EXE_NAME} X11) +ENDIF() target_include_directories(${EXE_NAME} PRIVATE diff --git a/plugins/vst_base/VstPlugin.cpp b/plugins/vst_base/VstPlugin.cpp index a08ef072d5e..b0f072a5a46 100644 --- a/plugins/vst_base/VstPlugin.cpp +++ b/plugins/vst_base/VstPlugin.cpp @@ -78,6 +78,7 @@ enum class MachineType : uint16_t unknown = 0x0, amd64 = 0x8664, i386 = 0x14c, + linux64 = 0x1, }; class FileInfo @@ -129,12 +130,18 @@ VstPlugin::VstPlugin( const QString & _plugin ) : setSplittedChannels( true ); PE::MachineType machineType; - try { - PE::FileInfo peInfo(m_plugin); - machineType = peInfo.machineType(); - } catch (std::runtime_error& e) { - qCritical() << "Error while determining PE file's machine type: " << e.what(); - machineType = PE::MachineType::unknown; + QFileInfo fi(m_plugin); + if (fi.completeSuffix() == "so") + machineType =PE::MachineType::linux64; + else + { + try { + PE::FileInfo peInfo(m_plugin); + machineType = peInfo.machineType(); + } catch (std::runtime_error& e) { + qCritical() << "Error while determining PE file's machine type: " << e.what(); + machineType = PE::MachineType::unknown; + } } switch(machineType) @@ -145,6 +152,9 @@ VstPlugin::VstPlugin( const QString & _plugin ) : case PE::MachineType::i386: tryLoad( REMOTE_VST_PLUGIN_FILEPATH_32 ); // Default: 32/RemoteVstPlugin32 break; + case PE::MachineType::linux64: + tryLoad( NATIVE_LINUX_REMOTE_VST_PLUGIN_FILEPATH_64 ); // Default: NativeLinuxRemoteVstPlugin32 + break; default: m_failed = true; return; diff --git a/plugins/vst_base/vstbase/CMakeLists.txt b/plugins/vst_base/vstbase/CMakeLists.txt index bd5f98b561e..f827696b296 100644 --- a/plugins/vst_base/vstbase/CMakeLists.txt +++ b/plugins/vst_base/vstbase/CMakeLists.txt @@ -1,5 +1,6 @@ ADD_DEFINITIONS(-DREMOTE_VST_PLUGIN_FILEPATH_32="${REMOTE_VST_PLUGIN_FILEPATH_32}") ADD_DEFINITIONS(-DREMOTE_VST_PLUGIN_FILEPATH_64="${REMOTE_VST_PLUGIN_FILEPATH_64}") +ADD_DEFINITIONS(-DNATIVE_LINUX_REMOTE_VST_PLUGIN_FILEPATH_64="${NATIVE_LINUX_REMOTE_VST_PLUGIN_FILEPATH_64}") BUILD_PLUGIN(vstbase ../vst_base.cpp ../VstPlugin.cpp ../VstPlugin.h ../communication.h From 3f56bd627c6acb078ac0e494b4d80d331d7dbfab Mon Sep 17 00:00:00 2001 From: akimaze Date: Sun, 6 Jun 2021 22:33:56 +0200 Subject: [PATCH 02/23] Use mutex for UI message processing. --- include/RemotePlugin.h | 1 + plugins/vst_base/RemoteVstPlugin.cpp | 120 ++++++++++----------------- 2 files changed, 46 insertions(+), 75 deletions(-) diff --git a/include/RemotePlugin.h b/include/RemotePlugin.h index 862370d1f20..44be67c4c0a 100644 --- a/include/RemotePlugin.h +++ b/include/RemotePlugin.h @@ -439,6 +439,7 @@ enum RemoteMessageIDs IdSavePresetFile, IdLoadPresetFile, IdDebugMessage, + IdIdle, IdUserBase = 64 } ; diff --git a/plugins/vst_base/RemoteVstPlugin.cpp b/plugins/vst_base/RemoteVstPlugin.cpp index c0bb1e72017..bcf29523033 100644 --- a/plugins/vst_base/RemoteVstPlugin.cpp +++ b/plugins/vst_base/RemoteVstPlugin.cpp @@ -70,6 +70,7 @@ #include #include #include +#include // https://stackoverflow.com/questions/22476110/c-compiling-error-including-x11-x-h-x11-xlib-h #undef Bool @@ -348,7 +349,13 @@ class RemoteVstPlugin : public RemotePluginClient } inline void queueMessage( const message & m ) { + #ifdef NATIVE_LINUX_VST + pthread_mutex_lock(&message_mutex); + #endif m_messageList.push( m ); + #ifdef NATIVE_LINUX_VST + pthread_mutex_unlock(&message_mutex); + #endif } inline bool shouldGiveIdle() const @@ -445,8 +452,6 @@ class RemoteVstPlugin : public RemotePluginClient Window m_window; Display* m_display; Atom wmDeleteMessage; - Atom lmmsUiEvent; - Atom lmmsX11GiveIdle; bool m_x11WindowVisible = false; #endif intptr_t m_windowID; @@ -458,6 +463,9 @@ class RemoteVstPlugin : public RemotePluginClient bool m_processing; +#ifdef NATIVE_LINUX_VST + pthread_mutex_t message_mutex = PTHREAD_MUTEX_INITIALIZER; +#endif std::queue m_messageList; bool m_shouldGiveIdle; @@ -637,7 +645,6 @@ bool RemoteVstPlugin::processMessage( const message & _m ) return true; case IdToggleUI: - debugMessage("toogle 5"); #ifndef NATIVE_LINUX_VST if( m_window && IsWindowVisible( m_window ) ) #else @@ -759,6 +766,12 @@ bool RemoteVstPlugin::processMessage( const message & _m ) break; } + + case IdIdle: + { + idle(); + break; + } default: return RemotePluginClient::processMessage( _m ); @@ -897,8 +910,6 @@ void RemoteVstPlugin::initEditor() wmDeleteMessage = XInternAtom(m_display, "WM_DELETE_WINDOW", false); XSetWMProtocols(m_display, m_window, &wmDeleteMessage, 1); - lmmsUiEvent = XInternAtom(m_display, "_APP_EVT", false); - lmmsX11GiveIdle = XInternAtom(m_display, "_APP_EVT_IDLE", false); // make tool window prop_atom = XInternAtom(m_display, "_NET_WM_WINDOW_TYPE", False); @@ -2181,6 +2192,10 @@ void RemoteVstPlugin::idle() void RemoteVstPlugin::processUIThreadMessages() { setProcessing( true ); + #ifdef NATIVE_LINUX_VST + pthread_mutex_lock(&message_mutex); + #endif + while( m_messageList.size() ) { processMessage( m_messageList.front() ); @@ -2191,24 +2206,18 @@ void RemoteVstPlugin::processUIThreadMessages() setShouldGiveIdle( false ); } } + #ifdef NATIVE_LINUX_VST + pthread_mutex_unlock(&message_mutex); + #endif + setProcessing( false ); + } #ifdef NATIVE_LINUX_VST void RemoteVstPlugin::sendX11Idle() { - if (m_window != NULL) - { - XEvent evt; - evt.xclient.type = ClientMessage; - evt.xclient.serial = 0; - evt.xclient.send_event = true; - evt.xclient.message_type = lmmsX11GiveIdle; - evt.xclient.format = 32; - evt.xclient.window = m_window; - XSendEvent(m_display, m_window, true, NoEventMask, &evt); - XFlush(m_display); - } + queueMessage(message( IdIdle )); } #endif @@ -2251,31 +2260,7 @@ void * RemoteVstPlugin::processingThread2(void * _param) ProcessPluginMessage, (LPARAM) new message( m ) ); #else - //_this->processMessage( m ); - - //_this->debugMessage("wysylaie"); - if (_this->m_window != NULL) - { - XEvent evt; - evt.xclient.type = ClientMessage; - evt.xclient.serial = 0; - evt.xclient.send_event = true; - evt.xclient.message_type = _this->lmmsUiEvent; - evt.xclient.format = 32; - evt.xclient.window = _this->m_window; - //evt.xclient.data.l[0] = XInternAtom(_this->m_display, "_APP_EVT_PTR", false); - uintptr_t val = uintptr_t(new message( m )); - //std::stringstream ss; - //ss << val; - //_this->debugMessage("wyslane: " + ss.str()); - //https://stackoverflow.com/questions/2810280/how-to-store-a-64-bit-integer-in-two-32-bit-integers-and-convert-back-again - //evt.xclient.data.l[0] = val; - evt.xclient.data.l[0] = (uint32_t)((val & 0xFFFFFFFF00000000LL) >> 32); - evt.xclient.data.l[1] = (uint32_t)(val & 0xFFFFFFFFLL); - //evt.xclient.data.l[0] = _this->lmmsUiEvent; - XSendEvent(_this->m_display, _this->m_window, true, NoEventMask, &evt); - XFlush(_this->m_display); - } + _this->queueMessage( m ); #endif } } @@ -2322,40 +2307,13 @@ void RemoteVstPlugin::guiEventLoop() XEvent e; while(true) { - if (XQLength(m_display) > 0) { + //if (XQLength(m_display) > 0) { + if (XPending(m_display) > 0) { XNextEvent(m_display, &e); if (e.type == ClientMessage) { - if (m_window == NULL || e.xclient.window != m_window) - continue; - if (e.xclient.message_type == lmmsX11GiveIdle) - { - //debugMessage("idle!!!"); - if (__plugin->isInitialized()) - __plugin->idle(); - return; - } - if (e.xclient.message_type == lmmsUiEvent) - { - //debugMessage("zdarzenie!!!"); - //uintptr_t mptr = ((uintptr_t)e.xclient.data.l[0]) << 32 | e.xclient.data.l[1]; - uintptr_t mptr = ((uintptr_t)e.xclient.data.l[0] << 32); - mptr = mptr | e.xclient.data.l[1]; - //std::stringstream ss; - //ss << mptr; - //debugMessage("znalezione " +ss.str()); - message * m = (message *) mptr; - if(__plugin->isInitialized()) - __plugin->queueMessage( *m ); - delete m; - if(__plugin->isInitialized() && !__plugin->isProcessing() ) - { - __plugin->processUIThreadMessages(); - } - - } - else if (e.xclient.data.l[0] == wmDeleteMessage) + if (e.xclient.data.l[0] == wmDeleteMessage) { //m_window = NULL; debugMessage("Hide editor"); @@ -2363,9 +2321,21 @@ void RemoteVstPlugin::guiEventLoop() } } } - /*else - if (__plugin->isInitialized()) - __plugin->idle();*/ + + // needed by zynaAddsubfx ui + if (__plugin->isInitialized()) + __plugin->idle(); + + if(__plugin->isInitialized() && !__plugin->isProcessing() ) + { + __plugin->processUIThreadMessages(); + } + + struct timespec tim, tim2; + tim.tv_sec = 0; + tim.tv_nsec = 500; + nanosleep(&tim, &tim2); + } } #endif From 3cd740afb3734526f70b500d4f63cf59cb3d61b5 Mon Sep 17 00:00:00 2001 From: akimaze Date: Wed, 9 Jun 2021 21:56:53 +0200 Subject: [PATCH 03/23] More fixes to native linux vst support. --- include/RemotePlugin.h | 11 +- plugins/vestige/vestige.cpp | 2 + .../NativeLinuxRemoteVstPlugin64.cmake | 2 +- plugins/vst_base/RemoteVstPlugin.cpp | 183 +++++++++++++----- plugins/vst_base/VstPlugin.cpp | 9 + 5 files changed, 152 insertions(+), 55 deletions(-) diff --git a/include/RemotePlugin.h b/include/RemotePlugin.h index 44be67c4c0a..1255ab44964 100644 --- a/include/RemotePlugin.h +++ b/include/RemotePlugin.h @@ -36,7 +36,6 @@ #include #include - #if !(defined(LMMS_HAVE_SYS_IPC_H) && defined(LMMS_HAVE_SEMAPHORE_H)) #define SYNC_WITH_SHM_FIFO #define USE_QT_SEMAPHORES @@ -826,6 +825,16 @@ class LMMS_EXPORT RemotePlugin : public QObject, public RemotePluginBase unlock(); } +#ifndef NATIVE_LINUX_VST + void setQuit() + { + + lock(); + sendMessage( IdQuit ); + unlock(); + } +#endif + int isUIVisible() { lock(); diff --git a/plugins/vestige/vestige.cpp b/plugins/vestige/vestige.cpp index 2d33ec961d2..b375f1c1ce7 100644 --- a/plugins/vestige/vestige.cpp +++ b/plugins/vestige/vestige.cpp @@ -682,7 +682,9 @@ void VestigeInstrumentView::openPlugin() QStringList types; types << tr( "DLL-files (*.dll)" ) << tr( "EXE-files (*.exe)" ) +#ifdef LMMS_BUILD_LINUX << tr( "SO-files (*.so)" ) +#endif ; ofd.setNameFilters( types ); diff --git a/plugins/vst_base/NativeLinuxRemoteVstPlugin64.cmake b/plugins/vst_base/NativeLinuxRemoteVstPlugin64.cmake index e04a030b23f..8d680081925 100644 --- a/plugins/vst_base/NativeLinuxRemoteVstPlugin64.cmake +++ b/plugins/vst_base/NativeLinuxRemoteVstPlugin64.cmake @@ -8,6 +8,6 @@ ELSEIF(LMMS_BUILD_LINUX) "-DCMAKE_CXX_FLAGS=-m64 -DNATIVE_LINUX_VST" "-DCMAKE_C_FLAGS=-DNATIVE_LINUX_VST" ) - INSTALL(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/../NativeLinuxRemoteVstPlugin64" "${CMAKE_CURRENT_BINARY_DIR}/../NativeLinuxRemoteVstPlugin64.so" DESTINATION "${PLUGIN_DIR}") + INSTALL(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/../NativeLinuxRemoteVstPlugin64" "${CMAKE_CURRENT_BINARY_DIR}/../NativeLinuxRemoteVstPlugin64" DESTINATION "${PLUGIN_DIR}") ENDIF() diff --git a/plugins/vst_base/RemoteVstPlugin.cpp b/plugins/vst_base/RemoteVstPlugin.cpp index bcf29523033..c6e27aa8a2c 100644 --- a/plugins/vst_base/RemoteVstPlugin.cpp +++ b/plugins/vst_base/RemoteVstPlugin.cpp @@ -349,13 +349,13 @@ class RemoteVstPlugin : public RemotePluginClient } inline void queueMessage( const message & m ) { - #ifdef NATIVE_LINUX_VST +#ifdef NATIVE_LINUX_VST pthread_mutex_lock(&message_mutex); - #endif +#endif m_messageList.push( m ); - #ifdef NATIVE_LINUX_VST +#ifdef NATIVE_LINUX_VST pthread_mutex_unlock(&message_mutex); - #endif +#endif } inline bool shouldGiveIdle() const @@ -375,7 +375,7 @@ class RemoteVstPlugin : public RemotePluginClient #ifndef NATIVE_LINUX_VST static DWORD WINAPI processingThread( LPVOID _param ); #else - static void * processingThread2( void * _param ); + static void * processingThread( void * _param ); #endif static bool setupMessageWindow(); @@ -442,16 +442,16 @@ class RemoteVstPlugin : public RemotePluginClient #ifndef NATIVE_LINUX_VST HINSTANCE m_libInst; #else - void* m_libInst; + void* m_libInst = NULL; #endif AEffect * m_plugin; #ifndef NATIVE_LINUX_VST HWND m_window; #else - Window m_window; - Display* m_display; - Atom wmDeleteMessage; + Window m_window = NULL; + Display* m_display = NULL; + Atom m_wmDeleteMessage; bool m_x11WindowVisible = false; #endif intptr_t m_windowID; @@ -465,6 +465,7 @@ class RemoteVstPlugin : public RemotePluginClient #ifdef NATIVE_LINUX_VST pthread_mutex_t message_mutex = PTHREAD_MUTEX_INITIALIZER; + bool m_shouldQuit = false; #endif std::queue m_messageList; bool m_shouldGiveIdle; @@ -618,7 +619,7 @@ RemoteVstPlugin::~RemoteVstPlugin() #ifndef NATIVE_LINUX_VST FreeLibrary( m_libInst ); #else - dlclose( m_libInst ); + dlclose(m_libInst); #endif m_libInst = NULL; } @@ -766,13 +767,22 @@ bool RemoteVstPlugin::processMessage( const message & _m ) break; } - + case IdIdle: { +#ifdef NATIVE_LINUX_VST idle(); +#endif break; } - + +#ifdef NATIVE_LINUX_VST + case IdQuit: + { + m_shouldQuit = true; + break; + } +#endif default: return RemotePluginClient::processMessage( _m ); } @@ -901,6 +911,8 @@ void RemoteVstPlugin::initEditor() #endif #else + // native linux support + // inspired by https://github.com/ekenberg/vstminihost XEvent e; Atom prop_atom, val_atom; @@ -908,8 +920,8 @@ void RemoteVstPlugin::initEditor() m_display = XOpenDisplay(NULL); m_window = XCreateSimpleWindow(m_display, DefaultRootWindow(m_display), 0, 0, 400, 400, 0, 0, 0); - wmDeleteMessage = XInternAtom(m_display, "WM_DELETE_WINDOW", false); - XSetWMProtocols(m_display, m_window, &wmDeleteMessage, 1); + m_wmDeleteMessage = XInternAtom(m_display, "WM_DELETE_WINDOW", false); + XSetWMProtocols(m_display, m_window, &m_wmDeleteMessage, 1); // make tool window prop_atom = XInternAtom(m_display, "_NET_WM_WINDOW_TYPE", False); @@ -917,10 +929,10 @@ void RemoteVstPlugin::initEditor() XChangeProperty(m_display, m_window, prop_atom, XA_ATOM, 32, PropModeReplace, (unsigned char *)&val_atom, 1); // change name - XStoreName(m_display, m_window, "LVSL"); + XStoreName(m_display, m_window, pluginName()); ERect * er; - pluginDispatch( effEditGetRect, 0, 0, &er ); + pluginDispatch(effEditGetRect, 0, 0, &er); m_windowWidth = er->right - er->left; m_windowHeight = er->bottom - er->top; @@ -929,12 +941,12 @@ void RemoteVstPlugin::initEditor() XMapWindow(m_display, m_window); XFlush(m_display); - pluginDispatch( effEditOpen, 0, (intptr_t) m_display, (void*) m_window ); + pluginDispatch(effEditOpen, 0, (intptr_t) m_display, (void*) m_window); XSelectInput(m_display, m_window, SubstructureNotifyMask | ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | ExposureMask | KeyPressMask); - pluginDispatch( effEditTop ); + pluginDispatch(effEditTop); m_x11WindowVisible = true; #endif } @@ -948,10 +960,13 @@ void RemoteVstPlugin::showEditor() { #ifndef NATIVE_LINUX_VST ShowWindow( m_window, SW_SHOWNORMAL ); #else - debugMessage("show editor"); - XMapWindow(m_display, m_window); - XFlush(m_display); - m_x11WindowVisible = true; + if (!m_x11WindowVisible) + { + debugMessage("show editor"); + XMapWindow(m_display, m_window); + XFlush(m_display); + m_x11WindowVisible = true; + } #endif } } @@ -965,10 +980,13 @@ void RemoteVstPlugin::hideEditor() { #ifndef NATIVE_LINUX_VST ShowWindow( m_window, SW_HIDE ); #else - debugMessage("hide editor"); - XUnmapWindow(m_display, m_window); - XFlush(m_display); - m_x11WindowVisible = false; + if (m_x11WindowVisible) + { + debugMessage("hide editor"); + XUnmapWindow(m_display, m_window); + XFlush(m_display); + m_x11WindowVisible = false; + } #endif } } @@ -978,7 +996,6 @@ void RemoteVstPlugin::hideEditor() { void RemoteVstPlugin::destroyEditor() { - debugMessage("destroy editor"); if( m_window == NULL ) { return; @@ -989,7 +1006,9 @@ void RemoteVstPlugin::destroyEditor() #ifndef NATIVE_LINUX_VST DestroyWindow( m_window ); #else - XCloseDisplay(m_display); + if (m_display) + XCloseDisplay(m_display); + m_display = NULL; #endif m_window = NULL; } @@ -2192,23 +2211,53 @@ void RemoteVstPlugin::idle() void RemoteVstPlugin::processUIThreadMessages() { setProcessing( true ); - #ifdef NATIVE_LINUX_VST - pthread_mutex_lock(&message_mutex); - #endif +#ifdef NATIVE_LINUX_VST + pthread_mutex_lock(&message_mutex); +#endif - while( m_messageList.size() ) + size_t size = m_messageList.size(); + +#ifdef NATIVE_LINUX_VST + pthread_mutex_unlock(&message_mutex); +#endif + + while( size ) { - processMessage( m_messageList.front() ); + +#ifdef NATIVE_LINUX_VST + pthread_mutex_lock(&message_mutex); +#endif + + message m = m_messageList.front(); + +#ifdef NATIVE_LINUX_VST + pthread_mutex_unlock(&message_mutex); +#endif + + processMessage( m ); + +#ifdef NATIVE_LINUX_VST + pthread_mutex_lock(&message_mutex); +#endif + m_messageList.pop(); +#ifdef NATIVE_LINUX_VST + pthread_mutex_unlock(&message_mutex); +#endif if( shouldGiveIdle() ) { pluginDispatch( effEditIdle ); setShouldGiveIdle( false ); } - } - #ifdef NATIVE_LINUX_VST +#ifdef NATIVE_LINUX_VST + pthread_mutex_lock(&message_mutex); +#endif + + size = m_messageList.size(); +#ifdef NATIVE_LINUX_VST pthread_mutex_unlock(&message_mutex); - #endif +#endif + } setProcessing( false ); @@ -2225,14 +2274,14 @@ void RemoteVstPlugin::sendX11Idle() #ifndef NATIVE_LINUX_VST DWORD WINAPI RemoteVstPlugin::processingThread( LPVOID _param ) #else -void * RemoteVstPlugin::processingThread2(void * _param) +void * RemoteVstPlugin::processingThread(void * _param) #endif { - #ifndef NATIVE_LINUX_VST +#ifndef NATIVE_LINUX_VST __processingThreadId = GetCurrentThreadId(); - #else +#else __processingThreadId = pthread_self(); - #endif +#endif RemoteVstPlugin * _this = static_cast( _param ); @@ -2264,6 +2313,20 @@ void * RemoteVstPlugin::processingThread2(void * _param) #endif } } + +#ifndef NATIVE_LINUX_VST + // notify GUI thread about shutdown + PostMessage( __MessageHwnd, WM_USER, ClosePlugin, 0 ); + + return 0; +#else + if (m.id == IdQuit) + _this->queueMessage( m ); + + int *result = (int*) malloc(sizeof(int)); + *result = 0; + pthread_exit(result); +#endif } @@ -2307,19 +2370,19 @@ void RemoteVstPlugin::guiEventLoop() XEvent e; while(true) { - //if (XQLength(m_display) > 0) { - if (XPending(m_display) > 0) { - XNextEvent(m_display, &e); - - if (e.type == ClientMessage) + //if (XQLength(m_display) > 0) + if (XPending(m_display) > 0) { - if (e.xclient.data.l[0] == wmDeleteMessage) + XNextEvent(m_display, &e); + + if (e.type == ClientMessage) { - //m_window = NULL; - debugMessage("Hide editor"); - hideEditor(); + if (e.xclient.data.l[0] == m_wmDeleteMessage) + { + debugMessage("Hide editor"); + hideEditor(); + } } - } } // needed by zynaAddsubfx ui @@ -2333,9 +2396,14 @@ void RemoteVstPlugin::guiEventLoop() struct timespec tim, tim2; tim.tv_sec = 0; - tim.tv_nsec = 500; + tim.tv_nsec = 50000; nanosleep(&tim, &tim2); + if (m_shouldQuit) + { + __plugin->hideEditor(); + break; + } } } #endif @@ -2387,7 +2455,6 @@ LRESULT CALLBACK RemoteVstPlugin::wndProc( HWND hwnd, UINT uMsg, return DefWindowProc( hwnd, uMsg, wParam, lParam ); } - #endif @@ -2489,6 +2556,13 @@ int main( int _argc, char * * _argv ) } } +#ifdef NATIVE_LINUX_VST + if (EMBED) + { + cerr << "Native linux VST works only without embeding." << endl; + } +#endif + // constructor automatically will process messages until it receives // a IdVstLoadPlugin message and processes it #ifdef SYNC_WITH_SHM_FIFO @@ -2508,7 +2582,7 @@ int main( int _argc, char * * _argv ) __plugin, 0, NULL ) == NULL ) #else int err = 0; - err = pthread_create(&__processingThreadId, NULL, &RemoteVstPlugin::processingThread2, __plugin); + err = pthread_create(&__processingThreadId, NULL, &RemoteVstPlugin::processingThread, __plugin); if (err != 0) #endif { @@ -2518,6 +2592,9 @@ int main( int _argc, char * * _argv ) } __plugin->guiEventLoop(); +#ifdef NATIVE_LINUX_VST + pthread_join(__processingThreadId, NULL); +#endif } delete __plugin; diff --git a/plugins/vst_base/VstPlugin.cpp b/plugins/vst_base/VstPlugin.cpp index b0f072a5a46..c25e6c2a506 100644 --- a/plugins/vst_base/VstPlugin.cpp +++ b/plugins/vst_base/VstPlugin.cpp @@ -78,7 +78,9 @@ enum class MachineType : uint16_t unknown = 0x0, amd64 = 0x8664, i386 = 0x14c, +#ifdef LMMS_BUILD_LINUX linux64 = 0x1, +#endif }; class FileInfo @@ -131,9 +133,11 @@ VstPlugin::VstPlugin( const QString & _plugin ) : PE::MachineType machineType; QFileInfo fi(m_plugin); +#ifdef LMMS_BUILD_LINUX if (fi.completeSuffix() == "so") machineType =PE::MachineType::linux64; else +#endif { try { PE::FileInfo peInfo(m_plugin); @@ -152,9 +156,11 @@ VstPlugin::VstPlugin( const QString & _plugin ) : case PE::MachineType::i386: tryLoad( REMOTE_VST_PLUGIN_FILEPATH_32 ); // Default: 32/RemoteVstPlugin32 break; +#ifdef LMMS_BUILD_LINUX case PE::MachineType::linux64: tryLoad( NATIVE_LINUX_REMOTE_VST_PLUGIN_FILEPATH_64 ); // Default: NativeLinuxRemoteVstPlugin32 break; +#endif default: m_failed = true; return; @@ -178,6 +184,9 @@ VstPlugin::VstPlugin( const QString & _plugin ) : VstPlugin::~VstPlugin() { +#ifdef NATIVE_LINUX_VST + RemotePlugin::setQuit(); +#endif delete m_pluginWidget; } From da0d33514fbd4afff074400678f73ae617758e3c Mon Sep 17 00:00:00 2001 From: akimaze Date: Wed, 9 Jun 2021 22:05:39 +0200 Subject: [PATCH 04/23] Support plugin window size change. --- plugins/vst_base/RemoteVstPlugin.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/plugins/vst_base/RemoteVstPlugin.cpp b/plugins/vst_base/RemoteVstPlugin.cpp index c6e27aa8a2c..ad5ecc5346c 100644 --- a/plugins/vst_base/RemoteVstPlugin.cpp +++ b/plugins/vst_base/RemoteVstPlugin.cpp @@ -2026,9 +2026,9 @@ intptr_t RemoteVstPlugin::hostCallback( AEffect * _effect, int32_t _opcode, { return 0; } -#ifndef NATIVE_LINUX_VST __plugin->m_windowWidth = _index; __plugin->m_windowHeight = _value; +#ifndef NATIVE_LINUX_VST HWND window = __plugin->m_window; DWORD dwStyle = GetWindowLongPtr( window, GWL_STYLE ); RECT windowSize = { 0, 0, (int) _index, (int) _value }; @@ -2038,11 +2038,14 @@ intptr_t RemoteVstPlugin::hostCallback( AEffect * _effect, int32_t _opcode, windowSize.bottom - windowSize.top, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER ); +#else + XResizeWindow(__plugin->m_display, __plugin->m_window, (int) _index, (int) _value); + XFlush(__plugin->m_display); +#endif __plugin->sendMessage( message( IdVstPluginEditorGeometry ). addInt( __plugin->m_windowWidth ). addInt( __plugin->m_windowHeight ) ); -#endif return 1; } From 8a808b237923d5aeb38c3754ae6461ada24f8ae0 Mon Sep 17 00:00:00 2001 From: akimaze Date: Wed, 9 Jun 2021 22:42:03 +0200 Subject: [PATCH 05/23] Longer sleep in ui loop to safe CPU. --- plugins/vst_base/RemoteVstPlugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/vst_base/RemoteVstPlugin.cpp b/plugins/vst_base/RemoteVstPlugin.cpp index ad5ecc5346c..41835f2ff15 100644 --- a/plugins/vst_base/RemoteVstPlugin.cpp +++ b/plugins/vst_base/RemoteVstPlugin.cpp @@ -2399,7 +2399,7 @@ void RemoteVstPlugin::guiEventLoop() struct timespec tim, tim2; tim.tv_sec = 0; - tim.tv_nsec = 50000; + tim.tv_nsec = 5000000; nanosleep(&tim, &tim2); if (m_shouldQuit) From 58c405c2a5ca17d5c86b06d014179b62d3d1c331 Mon Sep 17 00:00:00 2001 From: akimaze Date: Sat, 12 Jun 2021 15:31:19 +0200 Subject: [PATCH 06/23] Remove some debug messages, pull out timespec out of the loop. --- plugins/vst_base/RemoteVstPlugin.cpp | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/plugins/vst_base/RemoteVstPlugin.cpp b/plugins/vst_base/RemoteVstPlugin.cpp index 41835f2ff15..d1edf7020f6 100644 --- a/plugins/vst_base/RemoteVstPlugin.cpp +++ b/plugins/vst_base/RemoteVstPlugin.cpp @@ -662,7 +662,6 @@ bool RemoteVstPlugin::processMessage( const message & _m ) return true; case IdIsUIVisible: - debugMessage("is visible?"); #ifndef NATIVE_LINUX_VST bool visible = m_window && IsWindowVisible( m_window ); #else @@ -962,7 +961,6 @@ void RemoteVstPlugin::showEditor() { #else if (!m_x11WindowVisible) { - debugMessage("show editor"); XMapWindow(m_display, m_window); XFlush(m_display); m_x11WindowVisible = true; @@ -982,7 +980,6 @@ void RemoteVstPlugin::hideEditor() { #else if (m_x11WindowVisible) { - debugMessage("hide editor"); XUnmapWindow(m_display, m_window); XFlush(m_display); m_x11WindowVisible = false; @@ -2370,6 +2367,10 @@ DWORD WINAPI RemoteVstPlugin::guiEventLoop() #else void RemoteVstPlugin::guiEventLoop() { + struct timespec tim, tim2; + tim.tv_sec = 0; + tim.tv_nsec = 5000000; + XEvent e; while(true) { @@ -2378,14 +2379,8 @@ void RemoteVstPlugin::guiEventLoop() { XNextEvent(m_display, &e); - if (e.type == ClientMessage) - { - if (e.xclient.data.l[0] == m_wmDeleteMessage) - { - debugMessage("Hide editor"); - hideEditor(); - } - } + if (e.type == ClientMessage && e.xclient.data.l[0] == m_wmDeleteMessage) + hideEditor(); } // needed by zynaAddsubfx ui @@ -2393,13 +2388,8 @@ void RemoteVstPlugin::guiEventLoop() __plugin->idle(); if(__plugin->isInitialized() && !__plugin->isProcessing() ) - { __plugin->processUIThreadMessages(); - } - struct timespec tim, tim2; - tim.tv_sec = 0; - tim.tv_nsec = 5000000; nanosleep(&tim, &tim2); if (m_shouldQuit) From d0d9a4dc5c6af69f31ccca14ef1cbc042e584df1 Mon Sep 17 00:00:00 2001 From: akimaze Date: Sat, 12 Jun 2021 15:42:00 +0200 Subject: [PATCH 07/23] Remove redundant blank line at the end of a code block. --- include/RemotePlugin.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/RemotePlugin.h b/include/RemotePlugin.h index 1255ab44964..76b8b586bb6 100644 --- a/include/RemotePlugin.h +++ b/include/RemotePlugin.h @@ -1009,7 +1009,6 @@ class RemotePluginClient : public RemotePluginBase sample_rate_t m_sampleRate; fpp_t m_bufferSize; - } ; #endif From 55de77a454f1ba213b677285992586e250e03e08 Mon Sep 17 00:00:00 2001 From: akimaze Date: Sat, 12 Jun 2021 15:46:36 +0200 Subject: [PATCH 08/23] Fix more formating issues. --- plugins/vst_base/RemoteVstPlugin.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/plugins/vst_base/RemoteVstPlugin.cpp b/plugins/vst_base/RemoteVstPlugin.cpp index d1edf7020f6..4b507db7fc4 100644 --- a/plugins/vst_base/RemoteVstPlugin.cpp +++ b/plugins/vst_base/RemoteVstPlugin.cpp @@ -2258,9 +2258,8 @@ void RemoteVstPlugin::processUIThreadMessages() pthread_mutex_unlock(&message_mutex); #endif } - + setProcessing( false ); - } #ifdef NATIVE_LINUX_VST @@ -2583,18 +2582,17 @@ int main( int _argc, char * * _argv ) "processingThread\n" ); return -1; } - + __plugin->guiEventLoop(); #ifdef NATIVE_LINUX_VST pthread_join(__processingThreadId, NULL); #endif } - + delete __plugin; #ifndef NATIVE_LINUX_VST OleUninitialize(); #endif return 0; - } From 33551adddacc1f806a27b4caf659456101579463 Mon Sep 17 00:00:00 2001 From: akimaze Date: Sat, 12 Jun 2021 15:51:07 +0200 Subject: [PATCH 09/23] Fix more formating issues. --- plugins/vst_base/RemoteVstPlugin.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/plugins/vst_base/RemoteVstPlugin.cpp b/plugins/vst_base/RemoteVstPlugin.cpp index 4b507db7fc4..edd9020a38f 100644 --- a/plugins/vst_base/RemoteVstPlugin.cpp +++ b/plugins/vst_base/RemoteVstPlugin.cpp @@ -2281,12 +2281,12 @@ void * RemoteVstPlugin::processingThread(void * _param) #else __processingThreadId = pthread_self(); #endif - + RemoteVstPlugin * _this = static_cast( _param ); RemotePluginClient::message m; while( ( m = _this->receiveMessage() ).id != IdQuit ) - { + { if( m.id == IdStartProcessing || m.id == IdMidiEvent @@ -2315,13 +2315,13 @@ void * RemoteVstPlugin::processingThread(void * _param) #ifndef NATIVE_LINUX_VST // notify GUI thread about shutdown - PostMessage( __MessageHwnd, WM_USER, ClosePlugin, 0 ); - - return 0; + PostMessage( __MessageHwnd, WM_USER, ClosePlugin, 0 ); + + return 0; #else if (m.id == IdQuit) _this->queueMessage( m ); - + int *result = (int*) malloc(sizeof(int)); *result = 0; pthread_exit(result); From 3240482de1b2bea5a8b01c0e1e67076c74bb7c10 Mon Sep 17 00:00:00 2001 From: akimaze Date: Sat, 12 Jun 2021 19:22:00 +0200 Subject: [PATCH 10/23] Small fix to load TyrellN6.64.so --- plugins/vst_base/VstPlugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/vst_base/VstPlugin.cpp b/plugins/vst_base/VstPlugin.cpp index c25e6c2a506..a7d92e1a896 100644 --- a/plugins/vst_base/VstPlugin.cpp +++ b/plugins/vst_base/VstPlugin.cpp @@ -134,7 +134,7 @@ VstPlugin::VstPlugin( const QString & _plugin ) : PE::MachineType machineType; QFileInfo fi(m_plugin); #ifdef LMMS_BUILD_LINUX - if (fi.completeSuffix() == "so") + if (fi.suffix() == "so") machineType =PE::MachineType::linux64; else #endif From 70210b92cdcb9f932fe25ec726c6f26587087269 Mon Sep 17 00:00:00 2001 From: Dominic Clark Date: Mon, 21 Feb 2022 22:33:27 +0000 Subject: [PATCH 11/23] Fix segfault when plugins have no GUI --- plugins/vst_base/RemoteVstPlugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/vst_base/RemoteVstPlugin.cpp b/plugins/vst_base/RemoteVstPlugin.cpp index edd9020a38f..35c6c1c7b43 100644 --- a/plugins/vst_base/RemoteVstPlugin.cpp +++ b/plugins/vst_base/RemoteVstPlugin.cpp @@ -2374,7 +2374,7 @@ void RemoteVstPlugin::guiEventLoop() while(true) { //if (XQLength(m_display) > 0) - if (XPending(m_display) > 0) + if (m_display && XPending(m_display) > 0) { XNextEvent(m_display, &e); From 8424f29a80094c02177c7421e157be3a04b85ce2 Mon Sep 17 00:00:00 2001 From: Dominic Clark Date: Wed, 23 Feb 2022 18:46:52 +0000 Subject: [PATCH 12/23] Enable dragging SO files from file browser --- plugins/vestige/vestige.cpp | 4 ++++ src/core/DataFile.cpp | 3 +++ src/gui/FileBrowser.cpp | 6 +++++- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/plugins/vestige/vestige.cpp b/plugins/vestige/vestige.cpp index b375f1c1ce7..745c6fdf1e4 100644 --- a/plugins/vestige/vestige.cpp +++ b/plugins/vestige/vestige.cpp @@ -78,7 +78,11 @@ Plugin::Descriptor Q_DECL_EXPORT vestige_plugin_descriptor = 0x0100, Plugin::Instrument, new PluginPixmapLoader( "logo" ), +#ifdef LMMS_BUILD_LINUX + "dll,so", +#else "dll", +#endif NULL } ; diff --git a/src/core/DataFile.cpp b/src/core/DataFile.cpp index 1ca63eb92a5..c29bf6e901c 100644 --- a/src/core/DataFile.cpp +++ b/src/core/DataFile.cpp @@ -210,6 +210,9 @@ bool DataFile::validate( QString extension ) ( extension == "xiz" && ! pluginFactory->pluginSupportingExtension(extension).isNull()) || extension == "sf2" || extension == "sf3" || extension == "pat" || extension == "mid" || extension == "dll" +#ifdef LMMS_BUILD_LINUX + || extension == "so" +#endif #ifdef LMMS_HAVE_LV2 || extension == "lv2" #endif diff --git a/src/gui/FileBrowser.cpp b/src/gui/FileBrowser.cpp index 60b62d9a275..86174d397b7 100644 --- a/src/gui/FileBrowser.cpp +++ b/src/gui/FileBrowser.cpp @@ -1250,7 +1250,11 @@ void FileItem::determineFileType( void ) m_type = MidiFile; m_handling = ImportAsProject; } - else if( ext == "dll" ) + else if( ext == "dll" +#ifdef LMMS_BUILD_LINUX + || ext == "so" +#endif + ) { m_type = VstPluginFile; m_handling = LoadByPlugin; From be8132146eb3df04f5cc5a680fab0c09bd96d05b Mon Sep 17 00:00:00 2001 From: Dominic Clark Date: Wed, 23 Feb 2022 20:35:34 +0000 Subject: [PATCH 13/23] Split executable type from PE machine type --- plugins/vst_base/VstPlugin.cpp | 40 +++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/plugins/vst_base/VstPlugin.cpp b/plugins/vst_base/VstPlugin.cpp index a7d92e1a896..52ec5036f64 100644 --- a/plugins/vst_base/VstPlugin.cpp +++ b/plugins/vst_base/VstPlugin.cpp @@ -78,9 +78,6 @@ enum class MachineType : uint16_t unknown = 0x0, amd64 = 0x8664, i386 = 0x14c, -#ifdef LMMS_BUILD_LINUX - linux64 = 0x1, -#endif }; class FileInfo @@ -119,6 +116,10 @@ class FileInfo } +enum class ExecutableType +{ + Unknown, Win32, Win64, Linux64, +}; VstPlugin::VstPlugin( const QString & _plugin ) : m_plugin( PathUtil::toAbsolute(_plugin) ), @@ -131,33 +132,46 @@ VstPlugin::VstPlugin( const QString & _plugin ) : { setSplittedChannels( true ); - PE::MachineType machineType; - QFileInfo fi(m_plugin); + auto pluginType = ExecutableType::Unknown; #ifdef LMMS_BUILD_LINUX + QFileInfo fi(m_plugin); if (fi.suffix() == "so") - machineType =PE::MachineType::linux64; - else + { + pluginType = ExecutableType::Linux64; + } + else #endif { try { PE::FileInfo peInfo(m_plugin); - machineType = peInfo.machineType(); + switch (peInfo.machineType()) + { + case PE::MachineType::amd64: + pluginType = ExecutableType::Win64; + break; + case PE::MachineType::i386: + pluginType = ExecutableType::Win32; + break; + default: + qWarning() << "Unknown PE machine type" + << QString::number(static_cast(peInfo.machineType()), 16); + break; + } } catch (std::runtime_error& e) { qCritical() << "Error while determining PE file's machine type: " << e.what(); - machineType = PE::MachineType::unknown; } } - switch(machineType) + switch(pluginType) { - case PE::MachineType::amd64: + case ExecutableType::Win64: tryLoad( REMOTE_VST_PLUGIN_FILEPATH_64 ); // Default: RemoteVstPlugin64 break; - case PE::MachineType::i386: + case ExecutableType::Win32: tryLoad( REMOTE_VST_PLUGIN_FILEPATH_32 ); // Default: 32/RemoteVstPlugin32 break; #ifdef LMMS_BUILD_LINUX - case PE::MachineType::linux64: + case ExecutableType::Linux64: tryLoad( NATIVE_LINUX_REMOTE_VST_PLUGIN_FILEPATH_64 ); // Default: NativeLinuxRemoteVstPlugin32 break; #endif From d4cd07d8bf3c88cde9ccc299855b6c188d6b2a83 Mon Sep 17 00:00:00 2001 From: Dominic Clark Date: Wed, 23 Feb 2022 21:08:32 +0000 Subject: [PATCH 14/23] Use `_WIN32` macro where appropriate --- include/aeffectx.h | 2 +- plugins/vst_base/RemoteVstPlugin.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/aeffectx.h b/include/aeffectx.h index 06503ce5bee..e52fce1f05f 100644 --- a/include/aeffectx.h +++ b/include/aeffectx.h @@ -29,7 +29,7 @@ #include // Calling convention -#ifndef NATIVE_LINUX_VST +#ifdef _WIN32 #define VST_CALL_CONV __cdecl #else #define VST_CALL_CONV diff --git a/plugins/vst_base/RemoteVstPlugin.cpp b/plugins/vst_base/RemoteVstPlugin.cpp index 35c6c1c7b43..baddc2554d0 100644 --- a/plugins/vst_base/RemoteVstPlugin.cpp +++ b/plugins/vst_base/RemoteVstPlugin.cpp @@ -156,7 +156,7 @@ DWORD __processingThreadId = 0; pthread_t __processingThreadId = 0; #endif -#ifndef NATIVE_LINUX_VST +#ifdef _WIN32 //Returns the last Win32 error, in string format. Returns an empty string if there is no error. std::string GetErrorAsString(DWORD errorMessageID) { From f9f80b7c0a675f8cff33d5c1e344e01dbfd08fe0 Mon Sep 17 00:00:00 2001 From: Dominic Clark Date: Wed, 23 Feb 2022 23:48:23 +0000 Subject: [PATCH 15/23] Tweak CMake code slightly --- plugins/vst_base/CMakeLists.txt | 9 ++++++--- plugins/vst_base/NativeLinuxRemoteVstPlugin64.cmake | 6 ++---- plugins/vst_base/RemoteVstPlugin/CMakeLists.txt | 8 +------- plugins/vst_base/vstbase/CMakeLists.txt | 4 +++- 4 files changed, 12 insertions(+), 15 deletions(-) diff --git a/plugins/vst_base/CMakeLists.txt b/plugins/vst_base/CMakeLists.txt index 30ac329bf21..68bdb99395a 100644 --- a/plugins/vst_base/CMakeLists.txt +++ b/plugins/vst_base/CMakeLists.txt @@ -8,7 +8,10 @@ INCLUDE(ExternalProject) # These variables are not meant to be used normally, except packaging SET(REMOTE_VST_PLUGIN_FILEPATH_32 "32/RemoteVstPlugin32" CACHE STRING "Relative file path to RemoteVstPlugin32") SET(REMOTE_VST_PLUGIN_FILEPATH_64 "RemoteVstPlugin64" CACHE STRING "Relative file path to RemoteVstPlugin64") -SET(NATIVE_LINUX_REMOTE_VST_PLUGIN_FILEPATH_64 "NativeLinuxRemoteVstPlugin64" CACHE STRING "Relative file path to NativeLinuxRemoteVstPlugin64") +IF(LMMS_BUILD_LINUX) + SET(NATIVE_LINUX_REMOTE_VST_PLUGIN_FILEPATH_64 "NativeLinuxRemoteVstPlugin64" + CACHE STRING "Relative file path to NativeLinuxRemoteVstPlugin64") +ENDIF() ADD_SUBDIRECTORY(vstbase) @@ -50,6 +53,6 @@ IF(WANT_VST_64) INCLUDE("${CMAKE_CURRENT_LIST_DIR}/RemoteVstPlugin64.cmake") ENDIF() -if(LMMS_BUILD_LINUX) -INCLUDE("${CMAKE_CURRENT_LIST_DIR}/NativeLinuxRemoteVstPlugin64.cmake") +IF(LMMS_BUILD_LINUX) + INCLUDE("${CMAKE_CURRENT_LIST_DIR}/NativeLinuxRemoteVstPlugin64.cmake") ENDIF() diff --git a/plugins/vst_base/NativeLinuxRemoteVstPlugin64.cmake b/plugins/vst_base/NativeLinuxRemoteVstPlugin64.cmake index 8d680081925..33a9243af42 100644 --- a/plugins/vst_base/NativeLinuxRemoteVstPlugin64.cmake +++ b/plugins/vst_base/NativeLinuxRemoteVstPlugin64.cmake @@ -1,6 +1,4 @@ -IF(LMMS_BUILD_WIN64) - RETURN() -ELSEIF(LMMS_BUILD_LINUX) +IF(LMMS_BUILD_LINUX) ExternalProject_Add(NativeLinuxRemoteVstPlugin64 "${EXTERNALPROJECT_ARGS}" CMAKE_ARGS @@ -8,6 +6,6 @@ ELSEIF(LMMS_BUILD_LINUX) "-DCMAKE_CXX_FLAGS=-m64 -DNATIVE_LINUX_VST" "-DCMAKE_C_FLAGS=-DNATIVE_LINUX_VST" ) - INSTALL(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/../NativeLinuxRemoteVstPlugin64" "${CMAKE_CURRENT_BINARY_DIR}/../NativeLinuxRemoteVstPlugin64" DESTINATION "${PLUGIN_DIR}") + INSTALL(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/../NativeLinuxRemoteVstPlugin64" DESTINATION "${PLUGIN_DIR}") ENDIF() diff --git a/plugins/vst_base/RemoteVstPlugin/CMakeLists.txt b/plugins/vst_base/RemoteVstPlugin/CMakeLists.txt index e80cfe755e6..a171447dc6f 100644 --- a/plugins/vst_base/RemoteVstPlugin/CMakeLists.txt +++ b/plugins/vst_base/RemoteVstPlugin/CMakeLists.txt @@ -10,10 +10,6 @@ CHECK_CXX_DEFINE(IS_WIN "_WIN32") CHECK_CXX_DEFINE(IS_WIN64 "_WIN64") CHECK_CXX_DEFINE(IS_MINGW "__MINGW32__") -#if(NOT IS_WIN) -# message(FATAL_ERROR "Toolchain used does not target windows.") -#ENDIF() - if(IS_WIN64 OR CMAKE_SIZEOF_VOID_P EQUAL 8) set(BITNESS 64) else() @@ -38,9 +34,7 @@ add_executable(${EXE_NAME} WIN32 if(IS_WIN) target_link_libraries(${EXE_NAME} ole32) else() - target_link_libraries(${EXE_NAME} pthread) - target_link_libraries(${EXE_NAME} dl) - target_link_libraries(${EXE_NAME} X11) + target_link_libraries(${EXE_NAME} pthread dl X11) ENDIF() target_include_directories(${EXE_NAME} diff --git a/plugins/vst_base/vstbase/CMakeLists.txt b/plugins/vst_base/vstbase/CMakeLists.txt index f827696b296..4e8cbd97ce4 100644 --- a/plugins/vst_base/vstbase/CMakeLists.txt +++ b/plugins/vst_base/vstbase/CMakeLists.txt @@ -1,6 +1,8 @@ ADD_DEFINITIONS(-DREMOTE_VST_PLUGIN_FILEPATH_32="${REMOTE_VST_PLUGIN_FILEPATH_32}") ADD_DEFINITIONS(-DREMOTE_VST_PLUGIN_FILEPATH_64="${REMOTE_VST_PLUGIN_FILEPATH_64}") -ADD_DEFINITIONS(-DNATIVE_LINUX_REMOTE_VST_PLUGIN_FILEPATH_64="${NATIVE_LINUX_REMOTE_VST_PLUGIN_FILEPATH_64}") +IF(LMMS_BUILD_LINUX) + ADD_DEFINITIONS(-DNATIVE_LINUX_REMOTE_VST_PLUGIN_FILEPATH_64="${NATIVE_LINUX_REMOTE_VST_PLUGIN_FILEPATH_64}") +ENDIF() BUILD_PLUGIN(vstbase ../vst_base.cpp ../VstPlugin.cpp ../VstPlugin.h ../communication.h From 6e168e2442c7a3fe150f9e96f6cec0ac948449cf Mon Sep 17 00:00:00 2001 From: Dominic Clark Date: Thu, 24 Feb 2022 18:40:39 +0000 Subject: [PATCH 16/23] Fix trailing whitespace and typos --- plugins/vst_base/RemoteVstPlugin.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/plugins/vst_base/RemoteVstPlugin.cpp b/plugins/vst_base/RemoteVstPlugin.cpp index baddc2554d0..a74a7c3c2a7 100644 --- a/plugins/vst_base/RemoteVstPlugin.cpp +++ b/plugins/vst_base/RemoteVstPlugin.cpp @@ -83,7 +83,7 @@ #undef FontChange #undef None #undef Status -#undef Unsorte +#undef Unsorted #endif #ifdef USE_MINGW_THREADS_REPLACEMENT @@ -662,7 +662,7 @@ bool RemoteVstPlugin::processMessage( const message & _m ) return true; case IdIsUIVisible: -#ifndef NATIVE_LINUX_VST +#ifndef NATIVE_LINUX_VST bool visible = m_window && IsWindowVisible( m_window ); #else bool visible = m_window && m_x11WindowVisible; @@ -674,7 +674,7 @@ bool RemoteVstPlugin::processMessage( const message & _m ) } else if (EMBED && _m.id == IdShowUI) { -#ifndef NATIVE_LINUX_VST +#ifndef NATIVE_LINUX_VST ShowWindow( m_window, SW_SHOWNORMAL ); UpdateWindow( m_window ); #endif @@ -975,10 +975,10 @@ void RemoteVstPlugin::showEditor() { void RemoteVstPlugin::hideEditor() { if( !EMBED && !HEADLESS && m_window ) { -#ifndef NATIVE_LINUX_VST +#ifndef NATIVE_LINUX_VST ShowWindow( m_window, SW_HIDE ); #else - if (m_x11WindowVisible) + if (m_x11WindowVisible) { XUnmapWindow(m_display, m_window); XFlush(m_display); @@ -1000,7 +1000,7 @@ void RemoteVstPlugin::destroyEditor() pluginDispatch( effEditClose ); // Destroying the window takes some time in Wine 1.8.5 -#ifndef NATIVE_LINUX_VST +#ifndef NATIVE_LINUX_VST DestroyWindow( m_window ); #else if (m_display) @@ -1058,7 +1058,7 @@ bool RemoteVstPlugin::load( const std::string & _plugin_file ) debugMessage( "could not find entry point\n" ); return false; } - + m_plugin = mainEntry( hostCallback ); if( m_plugin == NULL ) { @@ -2551,7 +2551,7 @@ int main( int _argc, char * * _argv ) #ifdef NATIVE_LINUX_VST if (EMBED) { - cerr << "Native linux VST works only without embeding." << endl; + cerr << "Native linux VST works only without embedding." << endl; } #endif From 74ceb2c2f8c17bbea264fd8cf8249623c7267bb0 Mon Sep 17 00:00:00 2001 From: Dominic Clark Date: Thu, 24 Feb 2022 19:44:06 +0000 Subject: [PATCH 17/23] Adjust platform-specific scoping slightly --- plugins/vst_base/RemoteVstPlugin.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/plugins/vst_base/RemoteVstPlugin.cpp b/plugins/vst_base/RemoteVstPlugin.cpp index a74a7c3c2a7..ba015e6a642 100644 --- a/plugins/vst_base/RemoteVstPlugin.cpp +++ b/plugins/vst_base/RemoteVstPlugin.cpp @@ -58,8 +58,8 @@ #endif -#define USE_WS_PREFIX #ifndef NATIVE_LINUX_VST +#define USE_WS_PREFIX #include #else #include @@ -370,7 +370,9 @@ class RemoteVstPlugin : public RemotePluginClient void idle(); void processUIThreadMessages(); +#ifdef NATIVE_LINUX_VST void sendX11Idle(); +#endif #ifndef NATIVE_LINUX_VST static DWORD WINAPI processingThread( LPVOID _param ); @@ -999,8 +1001,8 @@ void RemoteVstPlugin::destroyEditor() } pluginDispatch( effEditClose ); - // Destroying the window takes some time in Wine 1.8.5 #ifndef NATIVE_LINUX_VST + // Destroying the window takes some time in Wine 1.8.5 DestroyWindow( m_window ); #else if (m_display) @@ -2313,8 +2315,8 @@ void * RemoteVstPlugin::processingThread(void * _param) } } -#ifndef NATIVE_LINUX_VST // notify GUI thread about shutdown +#ifndef NATIVE_LINUX_VST PostMessage( __MessageHwnd, WM_USER, ClosePlugin, 0 ); return 0; From 789ccd1044a87cb68f61827f58517c59486e6cf2 Mon Sep 17 00:00:00 2001 From: Dominic Clark Date: Thu, 24 Feb 2022 19:51:32 +0000 Subject: [PATCH 18/23] Fix thread exit memory leak --- plugins/vst_base/RemoteVstPlugin.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/plugins/vst_base/RemoteVstPlugin.cpp b/plugins/vst_base/RemoteVstPlugin.cpp index ba015e6a642..6ccfe2fcf4b 100644 --- a/plugins/vst_base/RemoteVstPlugin.cpp +++ b/plugins/vst_base/RemoteVstPlugin.cpp @@ -2324,9 +2324,7 @@ void * RemoteVstPlugin::processingThread(void * _param) if (m.id == IdQuit) _this->queueMessage( m ); - int *result = (int*) malloc(sizeof(int)); - *result = 0; - pthread_exit(result); + return nullptr; #endif } From b8589e77283fd8a7ed6c8c88ffad547eaa7f8c79 Mon Sep 17 00:00:00 2001 From: Dominic Clark Date: Fri, 25 Feb 2022 00:13:54 +0000 Subject: [PATCH 19/23] Remove superfluous plugin exit mechanism --- include/RemotePlugin.h | 10 ---------- plugins/vst_base/VstPlugin.cpp | 3 --- 2 files changed, 13 deletions(-) diff --git a/include/RemotePlugin.h b/include/RemotePlugin.h index 76b8b586bb6..cf801633f31 100644 --- a/include/RemotePlugin.h +++ b/include/RemotePlugin.h @@ -825,16 +825,6 @@ class LMMS_EXPORT RemotePlugin : public QObject, public RemotePluginBase unlock(); } -#ifndef NATIVE_LINUX_VST - void setQuit() - { - - lock(); - sendMessage( IdQuit ); - unlock(); - } -#endif - int isUIVisible() { lock(); diff --git a/plugins/vst_base/VstPlugin.cpp b/plugins/vst_base/VstPlugin.cpp index 52ec5036f64..21fe7a82016 100644 --- a/plugins/vst_base/VstPlugin.cpp +++ b/plugins/vst_base/VstPlugin.cpp @@ -198,9 +198,6 @@ VstPlugin::VstPlugin( const QString & _plugin ) : VstPlugin::~VstPlugin() { -#ifdef NATIVE_LINUX_VST - RemotePlugin::setQuit(); -#endif delete m_pluginWidget; } From 2acb1e0c01a863f46a094d7760d0b5b31f48f057 Mon Sep 17 00:00:00 2001 From: Dominic Clark Date: Fri, 25 Feb 2022 18:22:31 +0000 Subject: [PATCH 20/23] Fix build after master merge --- plugins/vst_base/RemoteVstPlugin.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/vst_base/RemoteVstPlugin.cpp b/plugins/vst_base/RemoteVstPlugin.cpp index 55fbb8aeb63..9235ec6eb33 100644 --- a/plugins/vst_base/RemoteVstPlugin.cpp +++ b/plugins/vst_base/RemoteVstPlugin.cpp @@ -449,9 +449,9 @@ class RemoteVstPlugin : public RemotePluginClient AEffect * m_plugin; #ifndef NATIVE_LINUX_VST - HWND m_window; + HWND m_window = nullptr; #else - Window m_window = NULL; + Window m_window = 0; Display* m_display = NULL; Atom m_wmDeleteMessage; bool m_x11WindowVisible = false; @@ -513,7 +513,6 @@ RemoteVstPlugin::RemoteVstPlugin( const char * socketPath ) : #endif m_libInst( nullptr ), m_plugin( nullptr ), - m_window( nullptr ), m_windowID( 0 ), m_windowWidth( 0 ), m_windowHeight( 0 ), @@ -995,7 +994,7 @@ void RemoteVstPlugin::hideEditor() { void RemoteVstPlugin::destroyEditor() { - if( m_window == nullptr ) + if( !m_window ) { return; } @@ -1004,12 +1003,13 @@ void RemoteVstPlugin::destroyEditor() #ifndef NATIVE_LINUX_VST // Destroying the window takes some time in Wine 1.8.5 DestroyWindow( m_window ); + m_window = nullptr; #else if (m_display) XCloseDisplay(m_display); m_display = NULL; + m_window = 0; #endif - m_window = nullptr; } From fd72546bb9944a38f5670e2d90dcb4047252f89f Mon Sep 17 00:00:00 2001 From: Dominic Clark Date: Fri, 25 Feb 2022 18:27:04 +0000 Subject: [PATCH 21/23] Replace `NULL` with `nullptr` --- plugins/vst_base/RemoteVstPlugin.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/plugins/vst_base/RemoteVstPlugin.cpp b/plugins/vst_base/RemoteVstPlugin.cpp index 9235ec6eb33..9c94188b75d 100644 --- a/plugins/vst_base/RemoteVstPlugin.cpp +++ b/plugins/vst_base/RemoteVstPlugin.cpp @@ -444,7 +444,7 @@ class RemoteVstPlugin : public RemotePluginClient #ifndef NATIVE_LINUX_VST HINSTANCE m_libInst; #else - void* m_libInst = NULL; + void* m_libInst = nullptr; #endif AEffect * m_plugin; @@ -452,7 +452,7 @@ class RemoteVstPlugin : public RemotePluginClient HWND m_window = nullptr; #else Window m_window = 0; - Display* m_display = NULL; + Display* m_display = nullptr; Atom m_wmDeleteMessage; bool m_x11WindowVisible = false; #endif @@ -916,8 +916,8 @@ void RemoteVstPlugin::initEditor() XEvent e; Atom prop_atom, val_atom; - if (m_display == NULL) - m_display = XOpenDisplay(NULL); + if (m_display == nullptr) + m_display = XOpenDisplay(nullptr); m_window = XCreateSimpleWindow(m_display, DefaultRootWindow(m_display), 0, 0, 400, 400, 0, 0, 0); m_wmDeleteMessage = XInternAtom(m_display, "WM_DELETE_WINDOW", false); @@ -1007,7 +1007,7 @@ void RemoteVstPlugin::destroyEditor() #else if (m_display) XCloseDisplay(m_display); - m_display = NULL; + m_display = nullptr; m_window = 0; #endif } @@ -1026,7 +1026,7 @@ bool RemoteVstPlugin::load( const std::string & _plugin_file ) } #else m_libInst = dlopen(_plugin_file.c_str(), RTLD_LAZY); - if ( m_libInst == NULL) { + if ( m_libInst == nullptr) { debugMessage( std::string("LoadLibrary failed: ") + dlerror() ); return false; } @@ -1049,9 +1049,9 @@ bool RemoteVstPlugin::load( const std::string & _plugin_file ) } #else mainEntryPointer mainEntry = (mainEntryPointer) dlsym(m_libInst, "VSTPluginMain"); - if( mainEntry == NULL ) + if( mainEntry == nullptr ) mainEntry = (mainEntryPointer) dlsym(m_libInst, "VstPluginMain"); - if( mainEntry == NULL ) + if( mainEntry == nullptr ) mainEntry = (mainEntryPointer) dlsym(m_libInst, "main"); #endif @@ -1064,7 +1064,7 @@ bool RemoteVstPlugin::load( const std::string & _plugin_file ) m_plugin = mainEntry( hostCallback ); if( m_plugin == nullptr ) { - debugMessage( "mainEntry procedure returned NULL\n" ); + debugMessage( "mainEntry procedure returned nullptr\n" ); return false; } @@ -1850,7 +1850,7 @@ intptr_t RemoteVstPlugin::hostCallback( AEffect * _effect, int32_t _opcode, // items may require extensive conversions // Shared memory was initialised? - see song.cpp - //assert( __plugin->m_vstSyncData != NULL ); + //assert( __plugin->m_vstSyncData != nullptr ); memset( &_timeInfo, 0, sizeof( _timeInfo ) ); _timeInfo.samplePos = __plugin->m_currentSamplePos; @@ -2575,7 +2575,7 @@ int main( int _argc, char * * _argv ) __plugin, 0, nullptr ) == nullptr ) #else int err = 0; - err = pthread_create(&__processingThreadId, NULL, &RemoteVstPlugin::processingThread, __plugin); + err = pthread_create(&__processingThreadId, nullptr, &RemoteVstPlugin::processingThread, __plugin); if (err != 0) #endif { @@ -2586,7 +2586,7 @@ int main( int _argc, char * * _argv ) __plugin->guiEventLoop(); #ifdef NATIVE_LINUX_VST - pthread_join(__processingThreadId, NULL); + pthread_join(__processingThreadId, nullptr); #endif } From 6b4c15190627f26411b4fcd1eac29ef4166381d9 Mon Sep 17 00:00:00 2001 From: Dominic Clark Date: Fri, 25 Feb 2022 23:06:59 +0000 Subject: [PATCH 22/23] Fix formatting --- plugins/vst_base/NativeLinuxRemoteVstPlugin64.cmake | 2 +- plugins/vst_base/RemoteVstPlugin.cpp | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/plugins/vst_base/NativeLinuxRemoteVstPlugin64.cmake b/plugins/vst_base/NativeLinuxRemoteVstPlugin64.cmake index 33a9243af42..dc582360429 100644 --- a/plugins/vst_base/NativeLinuxRemoteVstPlugin64.cmake +++ b/plugins/vst_base/NativeLinuxRemoteVstPlugin64.cmake @@ -4,7 +4,7 @@ IF(LMMS_BUILD_LINUX) CMAKE_ARGS "${EXTERNALPROJECT_CMAKE_ARGS}" "-DCMAKE_CXX_FLAGS=-m64 -DNATIVE_LINUX_VST" - "-DCMAKE_C_FLAGS=-DNATIVE_LINUX_VST" + "-DCMAKE_C_FLAGS=-DNATIVE_LINUX_VST" ) INSTALL(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/../NativeLinuxRemoteVstPlugin64" DESTINATION "${PLUGIN_DIR}") ENDIF() diff --git a/plugins/vst_base/RemoteVstPlugin.cpp b/plugins/vst_base/RemoteVstPlugin.cpp index 9c94188b75d..6b78c3a258d 100644 --- a/plugins/vst_base/RemoteVstPlugin.cpp +++ b/plugins/vst_base/RemoteVstPlugin.cpp @@ -917,7 +917,9 @@ void RemoteVstPlugin::initEditor() Atom prop_atom, val_atom; if (m_display == nullptr) + { m_display = XOpenDisplay(nullptr); + } m_window = XCreateSimpleWindow(m_display, DefaultRootWindow(m_display), 0, 0, 400, 400, 0, 0, 0); m_wmDeleteMessage = XInternAtom(m_display, "WM_DELETE_WINDOW", false); @@ -1006,7 +1008,9 @@ void RemoteVstPlugin::destroyEditor() m_window = nullptr; #else if (m_display) + { XCloseDisplay(m_display); + } m_display = nullptr; m_window = 0; #endif @@ -2322,7 +2326,9 @@ void * RemoteVstPlugin::processingThread(void * _param) return 0; #else if (m.id == IdQuit) + { _this->queueMessage( m ); + } return nullptr; #endif @@ -2380,15 +2386,21 @@ void RemoteVstPlugin::guiEventLoop() XNextEvent(m_display, &e); if (e.type == ClientMessage && e.xclient.data.l[0] == m_wmDeleteMessage) + { hideEditor(); + } } // needed by zynaAddsubfx ui if (__plugin->isInitialized()) + { __plugin->idle(); + } if(__plugin->isInitialized() && !__plugin->isProcessing() ) + { __plugin->processUIThreadMessages(); + } nanosleep(&tim, &tim2); From e71c737a829b8e3ff7cf939df24d7ae31fbd2c71 Mon Sep 17 00:00:00 2001 From: Dominic Clark Date: Sat, 26 Feb 2022 16:51:49 +0000 Subject: [PATCH 23/23] Fix typo and author information --- plugins/vst_base/RemoteVstPlugin.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/plugins/vst_base/RemoteVstPlugin.cpp b/plugins/vst_base/RemoteVstPlugin.cpp index 6b78c3a258d..30bb7919e3b 100644 --- a/plugins/vst_base/RemoteVstPlugin.cpp +++ b/plugins/vst_base/RemoteVstPlugin.cpp @@ -10,6 +10,9 @@ * Copyright (c) 2004 Torben Hohn * Copyright (c) 2002 Kjetil S. Matheussen * + * X11 code partly taken from https://github.com/ekenberg/vstminihost: + * Copyright (c) 2012 Johan Ekenberg + * * 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 @@ -911,8 +914,6 @@ void RemoteVstPlugin::initEditor() #endif #else - // native linux support - // inspired by https://github.com/ekenberg/vstminihost XEvent e; Atom prop_atom, val_atom; @@ -2391,7 +2392,7 @@ void RemoteVstPlugin::guiEventLoop() } } - // needed by zynaAddsubfx ui + // needed by ZynAddSubFX UI if (__plugin->isInitialized()) { __plugin->idle();