Support ZynAddSubFx with MSVC (#6561)

This commit is contained in:
Dominic Clark
2023-01-02 23:42:46 +00:00
committed by GitHub
parent 79def0c3b5
commit d95c89760a
10 changed files with 120 additions and 135 deletions

View File

@@ -225,8 +225,8 @@ jobs:
--triplet=${{ matrix.arch }}-windows `
--host-triplet=${{ matrix.arch }}-windows `
--recurse `
fftw3 fluidsynth[sndfile] libsamplerate libsndfile libstk lilv lv2 `
portaudio sdl2
fftw3 fltk fluidsynth[sndfile] libsamplerate libsndfile libstk `
lilv lv2 portaudio sdl2
- name: Set up build environment
uses: ilammy/msvc-dev-cmd@d8610e2b41c6d0f0c3b4c46dad8df0fd826c68e1
with:

View File

@@ -486,6 +486,13 @@ ENDIF(WANT_JACK)
FIND_PACKAGE(FFTW COMPONENTS fftw3f REQUIRED)
# check for FLTK
set(FLTK_SKIP_OPENGL TRUE)
set(FLTK_SKIP_FORMS TRUE)
set(FLTK_SKIP_IMAGES TRUE)
set(FLTK_SKIP_MATH TRUE)
if(MINGW_PREFIX)
set(FLTK_SKIP_FLUID TRUE)
endif()
FIND_PACKAGE(FLTK)
IF(FLTK_FOUND)
SET(STATUS_ZYN "OK")

View File

@@ -100,7 +100,6 @@ ENDIF()
IF(MSVC)
SET(MSVC_INCOMPATIBLE_PLUGINS
LadspaEffect
ZynAddSubFx
)
message(WARNING "Compiling with MSVC. The following plugins are not available: ${MSVC_INCOMPATIBLE_PLUGINS}")
LIST(REMOVE_ITEM PLUGIN_LIST ${MSVC_INCOMPATIBLE_PLUGINS})

View File

@@ -47,7 +47,7 @@ namespace lmms
#ifdef _WIN32
std::wstring toWString(const std::string& s)
inline std::wstring toWString(const std::string& s)
{
std::wstring ret;
int len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, s.data(),
@@ -64,7 +64,7 @@ std::wstring toWString(const std::string& s)
#endif
FILE* F_OPEN_UTF8(std::string const& fname, const char* mode){
inline FILE* F_OPEN_UTF8(std::string const& fname, const char* mode){
#ifdef LMMS_BUILD_WIN32
return _wfopen(toWString(fname).data(), toWString(mode).data());
#else
@@ -73,7 +73,7 @@ FILE* F_OPEN_UTF8(std::string const& fname, const char* mode){
}
int fileToDescriptor(FILE* f, bool closeFile = true)
inline int fileToDescriptor(FILE* f, bool closeFile = true)
{
int fh;
if (f == nullptr) {return -1;}

View File

@@ -1,5 +1,12 @@
if(NOT FLTK_FOUND)
return()
endif()
INCLUDE(BuildPlugin)
find_package(Threads REQUIRED)
find_package(ZLIB REQUIRED)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
# definitions for ZynAddSubFX
@@ -11,40 +18,20 @@ ELSE()
ADD_DEFINITIONS(-DOS_WINDOWS)
ENDIF()
# do not conflict with LMMS' Controller class
ADD_DEFINITIONS(-DController=ZynController)
# use asm optimizations when on x86 or x86_64
IF(LMMS_HOST_X86 OR LMMS_HOST_X86_64)
if(NOT MSVC AND (LMMS_HOST_X86 OR LMMS_HOST_X86_64))
ADD_DEFINITIONS(-DASM_F2I_YES)
ENDIF(LMMS_HOST_X86 OR LMMS_HOST_X86_64)
endif()
# build ZynAddSubFX with full optimizations
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -Wno-write-strings -Wno-deprecated-declarations -fpermissive")
if(NOT MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -Wno-write-strings -Wno-deprecated-declarations -fpermissive")
endif()
IF("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND NOT "${CMAKE_CXX_COMPILER_VERSION}" VERSION_LESS "6.0.0")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-misleading-indentation")
ENDIF()
IF(LMMS_BUILD_WIN32)
# link system-libraries
ADD_DEFINITIONS(-DPTW32_STATIC_LIB)
# fix X11 headers errors caused by bug with mingw + c++11 (enable -std=gnu++0x)
SET(CMAKE_CXX_EXTENSIONS ON)
ENDIF(LMMS_BUILD_WIN32)
SET(FLTK_SKIP_OPENGL TRUE)
SET(FLTK_SKIP_FORMS TRUE)
SET(FLTK_SKIP_IMAGES TRUE)
SET(FLTK_SKIP_MATH TRUE)
IF(MINGW_PREFIX)
SET(FLTK_SKIP_FLUID TRUE)
ENDIF()
IF(NOT FLTK_FOUND)
RETURN()
ENDIF()
IF(MINGW_PREFIX)
SET(FLTK_FLUID_EXECUTABLE "${MINGW_PREFIX}/bin/fluid")
ENDIF()
@@ -57,13 +44,15 @@ IF(NOT EXISTS ${FLTK_FLUID_EXECUTABLE})
ENDIF()
ENDIF()
INCLUDE_DIRECTORIES("${FLTK_INCLUDE_DIR}"
"${CMAKE_CURRENT_SOURCE_DIR}"
${FFTW3F_INCLUDE_DIRS}
"${CMAKE_CURRENT_BINARY_DIR}"
"${CMAKE_BINARY_DIR}")
include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/zynaddsubfx/src/UI)
include_directories(
"${FLTK_INCLUDE_DIR}"
"${CMAKE_CURRENT_SOURCE_DIR}"
${FFTW3F_INCLUDE_DIRS}
"${CMAKE_CURRENT_BINARY_DIR}"
"${CMAKE_BINARY_DIR}"
"${CMAKE_SOURCE_DIR}/src/3rdparty/mingw-std-threads"
"${CMAKE_CURRENT_SOURCE_DIR}/zynaddsubfx/src/UI"
)
ADD_DEFINITIONS(-DPLUGINVERSION) # removes exit confirmation dialogs etc. in MasterUI.fl
add_subdirectory(zynaddsubfx/src/Nio)
@@ -116,24 +105,23 @@ SET(zynaddsubfx_core_SRCS
zynaddsubfx/src/Synth/PADnote.cpp
zynaddsubfx/src/Synth/Resonance.cpp
zynaddsubfx/src/Synth/SUBnote.cpp
)
)
add_library(ZynAddSubFxCoreObjs OBJECT LocalZynAddSubFx.cpp ${zynaddsubfx_core_SRCS})
add_library(ZynAddSubFxCore INTERFACE)
target_sources(ZynAddSubFxCore INTERFACE
$<TARGET_OBJECTS:ZynAddSubFxCoreObjs>
$<TARGET_OBJECTS:zynaddsubfx_nio>
)
IF(LMMS_BUILD_LINUX)
ADD_LIBRARY(ZynAddSubFxCore MODULE LocalZynAddSubFx.cpp ${zynaddsubfx_core_SRCS})
ELSE()
ADD_LIBRARY(ZynAddSubFxCore SHARED LocalZynAddSubFx.cpp ${zynaddsubfx_core_SRCS})
ENDIF()
TARGET_LINK_LIBRARIES(ZynAddSubFxCore zynaddsubfx_nio ${FFTW3F_LIBRARIES} ${QT_LIBRARIES} -lz -lpthread)
TARGET_LINK_LIBRARIES(ZynAddSubFxCore Qt5::Widgets Qt5::Xml)
IF(LMMS_BUILD_WIN32)
TARGET_LINK_LIBRARIES(ZynAddSubFxCore -lws2_32)
INSTALL(TARGETS ZynAddSubFxCore RUNTIME DESTINATION "${PLUGIN_DIR}")
ELSE(LMMS_BUILD_WIN32)
INSTALL(TARGETS ZynAddSubFxCore LIBRARY DESTINATION "${PLUGIN_DIR}")
ENDIF(LMMS_BUILD_WIN32)
target_link_libraries(ZynAddSubFxCore INTERFACE
${FFTW3F_LIBRARIES}
${QT_LIBRARIES}
Qt5::Widgets
Qt5::Xml
Threads::Threads
ZLIB::ZLIB
)
LINK_DIRECTORIES("${CMAKE_CURRENT_BINARY_DIR}/..")
IF(LMMS_BUILD_LINUX)
@@ -144,10 +132,11 @@ ELSE()
SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${PLUGIN_DIR}")
ENDIF()
BUILD_PLUGIN(zynaddsubfx ZynAddSubFx.cpp ZynAddSubFx.h MOCFILES ZynAddSubFx.h EMBEDDED_RESOURCES artwork.png logo.png)
TARGET_LINK_LIBRARIES(zynaddsubfx -lZynAddSubFxCore)
ADD_DEPENDENCIES(zynaddsubfx ZynAddSubFxCore)
target_link_libraries(zynaddsubfx ZynAddSubFxCore)
IF(WIN32)
if(MSVC)
set(WINRC "${CMAKE_CURRENT_BINARY_DIR}/zynaddsubfx.rc")
elseif(WIN32)
SET(WINRC "${CMAKE_CURRENT_BINARY_DIR}/zynaddsubfxrc.obj")
ADD_CUSTOM_COMMAND(OUTPUT "${WINRC}"
COMMAND "${CMAKE_RC_COMPILER}"
@@ -155,14 +144,19 @@ IF(WIN32)
"-o\"${CMAKE_CURRENT_BINARY_DIR}/zynaddsubfxrc.obj\""
"-i\"${CMAKE_CURRENT_BINARY_DIR}/zynaddsubfx.rc\""
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/zynaddsubfx.rc")
ENDIF(WIN32)
endif()
# Use libraries in non-standard directories (e.g., another version of Qt)
SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
ADD_SUBDIRECTORY("${LMMS_SOURCE_DIR}/src/common" common)
ADD_EXECUTABLE(RemoteZynAddSubFx RemoteZynAddSubFx.cpp ${LMMS_COMMON_SRCS} "${WINRC}")
add_executable(RemoteZynAddSubFx
RemoteZynAddSubFx.cpp
${LMMS_COMMON_SRCS}
"${WINRC}"
$<TARGET_OBJECTS:zynaddsubfx_gui>
)
INSTALL(TARGETS RemoteZynAddSubFx RUNTIME DESTINATION "${PLUGIN_DIR}")
# Needed to deploy dependencies of RemoteZynAddSubFx
SET_PROPERTY(GLOBAL APPEND PROPERTY PLUGINS_BUILT "RemoteZynAddSubFx")
@@ -182,8 +176,7 @@ IF(FLTK_CONFIG AND NOT (LMMS_BUILD_APPLE OR LMMS_BUILD_WIN32))
STRING(REPLACE " " ";" FLTK_FILTERED_LDFLAGS ${FLTK_FILTERED_LDFLAGS})
LIST(REMOVE_ITEM FLTK_FILTERED_LDFLAGS -lX11)
ENDIF()
TARGET_LINK_LIBRARIES(RemoteZynAddSubFx zynaddsubfx_gui -lZynAddSubFxCore ${FLTK_FILTERED_LDFLAGS} -lpthread )
ADD_DEPENDENCIES(RemoteZynAddSubFx ZynAddSubFxCore)
target_link_libraries(RemoteZynAddSubFx ZynAddSubFxCore ${FLTK_FILTERED_LDFLAGS})
if(LMMS_HAVE_LIBRT)
target_link_libraries(RemoteZynAddSubFx rt)
@@ -199,13 +192,6 @@ ENDIF(LMMS_BUILD_WIN32)
IF(LMMS_BUILD_WIN32)
add_custom_command(
TARGET ZynAddSubFxCore
POST_BUILD
COMMAND "${STRIP_COMMAND}" "$<TARGET_FILE:ZynAddSubFxCore>"
VERBATIM
COMMAND_EXPAND_LISTS
)
add_custom_command(
TARGET RemoteZynAddSubFx
POST_BUILD

View File

@@ -22,19 +22,25 @@
*
*/
#include <lmmsconfig.h>
#include "LocalZynAddSubFx.h"
#include "zynaddsubfx/src/Misc/Util.h"
#include <unistd.h>
#include <ctime>
#include "LocalZynAddSubFx.h"
#include "lmmsconfig.h"
#ifdef LMMS_BUILD_WIN32
# include <wchar.h>
# include "IoHelper.h"
#else
# include <unistd.h>
#endif
#include "MidiEvent.h"
#include "zynaddsubfx/src/Nio/NulEngine.h"
#include "zynaddsubfx/src/Misc/Master.h"
#include "zynaddsubfx/src/Misc/Part.h"
#include "zynaddsubfx/src/Misc/Util.h"
// Global variable in zynaddsubfx/src/globals.h
SYNTH_T* synth = nullptr;
@@ -53,14 +59,6 @@ LocalZynAddSubFx::LocalZynAddSubFx() :
{
if( s_instanceCount == 0 )
{
#ifdef LMMS_BUILD_WIN32
#ifndef __WINPTHREADS_VERSION
// (non-portable) initialization of statically linked pthread library
pthread_win32_process_attach_np();
pthread_win32_thread_attach_np();
#endif
#endif // LMMS_BUILD_WIN32
initConfig();
synth = new SYNTH_T;
@@ -143,14 +141,20 @@ void LocalZynAddSubFx::loadXML( const std::string & _filename )
{
char * f = strdup( _filename.c_str() );
pthread_mutex_lock( &m_master->mutex );
m_master->defaults();
m_master->loadXML( f );
pthread_mutex_unlock( &m_master->mutex );
{
const auto lock = std::lock_guard{m_master->mutex};
m_master->defaults();
m_master->loadXML( f );
}
m_master->applyparameters();
#ifdef LMMS_BUILD_WIN32
_wunlink(toWString(_filename).c_str());
#else
unlink( f );
#endif
free( f );
}
@@ -161,10 +165,11 @@ void LocalZynAddSubFx::loadPreset( const std::string & _filename, int _part )
{
char * f = strdup( _filename.c_str() );
pthread_mutex_lock( &m_master->mutex );
m_master->part[_part]->defaultsinstrument();
m_master->part[_part]->loadXMLinstrument( f );
pthread_mutex_unlock( &m_master->mutex );
{
const auto lock = std::lock_guard{m_master->mutex};
m_master->part[_part]->defaultsinstrument();
m_master->part[_part]->loadXMLinstrument( f );
}
m_master->applyparameters();
@@ -262,8 +267,13 @@ void LocalZynAddSubFx::processMidiEvent( const MidiEvent& event )
void LocalZynAddSubFx::processAudio( sampleFrame * _out )
{
#ifdef _MSC_VER
const auto outputl = static_cast<float*>(_alloca(synth->buffersize * sizeof(float)));
const auto outputr = static_cast<float*>(_alloca(synth->buffersize * sizeof(float)));
#else
float outputl[synth->buffersize];
float outputr[synth->buffersize];
#endif
m_master->GetAudioOutSamples( synth->buffersize, synth->samplerate, outputl, outputr );

View File

@@ -22,17 +22,19 @@
*
*/
#include "RemoteZynAddSubFx.h"
#include <lmmsconfig.h>
#ifdef LMMS_BUILD_WIN32
#include <winsock2.h>
#endif
#include <queue>
#include "ThreadShims.h"
#undef CursorShape // is, by mistake, not undefed in FL
#include "RemotePluginClient.h"
#include "RemoteZynAddSubFx.h"
#include "LocalZynAddSubFx.h"
#include "zynaddsubfx/src/Nio/Nio.h"
@@ -60,12 +62,12 @@ public:
sendMessage( IdInitDone );
waitForMessage( IdInitDone );
pthread_mutex_init( &m_guiMutex, nullptr );
pthread_create( &m_messageThreadHandle, nullptr, messageLoop, this );
m_messageThread = std::thread{&RemoteZynAddSubFx::messageLoop, this};
}
~RemoteZynAddSubFx() override
{
m_messageThread.join();
Nio::stop();
}
@@ -84,9 +86,8 @@ public:
message m;
while( ( m = receiveMessage() ).id != IdQuit )
{
pthread_mutex_lock( &m_master->mutex );
const auto lock = std::lock_guard{m_master->mutex};
processMessage( m );
pthread_mutex_unlock( &m_master->mutex );
}
m_guiExit = true;
}
@@ -102,9 +103,10 @@ public:
case IdHideUI:
case IdLoadSettingsFromFile:
case IdLoadPresetFile:
pthread_mutex_lock( &m_guiMutex );
m_guiMessages.push( _m );
pthread_mutex_unlock( &m_guiMutex );
{
const auto lock = std::lock_guard{m_guiMutex};
m_guiMessages.push( _m );
}
break;
case IdSaveSettingsToFile:
@@ -144,22 +146,13 @@ public:
LocalZynAddSubFx::processAudio( _out );
}
static void * messageLoop( void * _arg )
{
auto _this = static_cast<RemoteZynAddSubFx*>(_arg);
_this->messageLoop();
return nullptr;
}
void guiLoop();
private:
const int m_guiSleepTime;
pthread_t m_messageThreadHandle;
pthread_mutex_t m_guiMutex;
std::thread m_messageThread;
std::mutex m_guiMutex;
std::queue<RemotePluginClient::message> m_guiMessages;
bool m_guiExit;
@@ -189,12 +182,11 @@ void RemoteZynAddSubFx::guiLoop()
}
if( exitProgram == 1 )
{
pthread_mutex_lock( &m_master->mutex );
const auto lock = std::lock_guard{m_master->mutex};
sendMessage( IdHideUI );
exitProgram = 0;
pthread_mutex_unlock( &m_master->mutex );
}
pthread_mutex_lock( &m_guiMutex );
const auto lock = std::lock_guard{m_guiMutex};
while( m_guiMessages.size() )
{
RemotePluginClient::message m = m_guiMessages.front();
@@ -219,9 +211,8 @@ void RemoteZynAddSubFx::guiLoop()
{
ui->refresh_master_ui();
}
pthread_mutex_lock( &m_master->mutex );
const auto lock = std::lock_guard{m_master->mutex};
sendMessage( IdLoadSettingsFromFile );
pthread_mutex_unlock( &m_master->mutex );
break;
}
@@ -235,9 +226,8 @@ void RemoteZynAddSubFx::guiLoop()
ui->updatepanel();
ui->refresh_master_ui();
}
pthread_mutex_lock( &m_master->mutex );
const auto lock = std::lock_guard{m_master->mutex};
sendMessage( IdLoadPresetFile );
pthread_mutex_unlock( &m_master->mutex );
break;
}
@@ -245,7 +235,6 @@ void RemoteZynAddSubFx::guiLoop()
break;
}
}
pthread_mutex_unlock( &m_guiMutex );
}
Fl::flush();
@@ -271,15 +260,6 @@ int main( int _argc, char * * _argv )
const auto pollParentThread = PollParentThread{};
#endif
#ifdef LMMS_BUILD_WIN32
#ifndef __WINPTHREADS_VERSION
// (non-portable) initialization of statically linked pthread library
pthread_win32_process_attach_np();
pthread_win32_thread_attach_np();
#endif
#endif // LMMS_BUILD_WIN32
#ifdef SYNC_WITH_SHM_FIFO
RemoteZynAddSubFx * remoteZASF =
new RemoteZynAddSubFx( _argv[1], _argv[2] );
@@ -291,14 +271,6 @@ int main( int _argc, char * * _argv )
delete remoteZASF;
#ifdef LMMS_BUILD_WIN32
#ifndef __WINPTHREADS_VERSION
pthread_win32_thread_detach_np();
pthread_win32_process_detach_np();
#endif
#endif // LMMS_BUILD_WIN32
return 0;
}

View File

@@ -0,0 +1,9 @@
#include <condition_variable>
#include <mutex>
#include <thread>
#if defined(__MINGW32__) && !defined(_GLIBCXX_HAS_GTHREADS)
# include <mingw.condition_variable.h>
# include <mingw.mutex.h>
# include <mingw.thread.h>
#endif

View File

@@ -77,7 +77,9 @@ exclude_files = re.compile(
'plugins/MidiExport/MidiFile.hpp|'
'plugins/ReverbSC/[a-z]|'
'plugins/Sf2Player/fluidsynthshims.h|'
'/portsmf/'
'/portsmf/|'
# only forward to headers that are not ours:
'plugins/ZynAddSubFx/ThreadShims.h'
)
files = [Path(f) for f in result.stdout.splitlines() if not exclude_files.search(f)]
@@ -131,7 +133,7 @@ for cur_file in files:
if cur_file.is_file():
cur_text = cur_file.read_text(errors='replace')
if str(cur_file) not in known_no_namespace_lmms:
if cur_file.as_posix() not in known_no_namespace_lmms:
namespace_pattern.search(cur_text) or error(cur_file, None, f'File has no namespace lmms')
header_guard = str(cur_file).endswith('.h')