mirror of
https://github.com/ZDoom/fluidsynth.git
synced 2025-04-11 10:20:50 +00:00
Compare commits
145 commits
v2.2.4
...
native_win
Author | SHA1 | Date | |
---|---|---|---|
|
2867c8d8db | ||
|
b58d142dd9 | ||
|
32f4347d26 | ||
|
85fcbde9e0 | ||
|
7e3fdc9056 | ||
|
57554ee35a | ||
|
24898c126d | ||
|
1f8c6a4633 | ||
|
9910b0dc9b | ||
|
a50680aafa | ||
|
3a3ed4f783 | ||
|
b274aaefba | ||
|
58ec0d8eb7 | ||
|
41f00ec8cb | ||
|
3591299ea0 | ||
|
ff362b52cd | ||
|
fe7fa3e309 | ||
|
1b4b7ddbfe | ||
|
b675a392ea | ||
|
f06619e079 | ||
|
a293761e44 | ||
|
7ede2382d3 | ||
|
0e0a287be4 | ||
|
0d0b4d4b84 | ||
|
d554067fc5 | ||
|
f013e82d58 | ||
|
eff5da51c4 | ||
|
308cf73796 | ||
|
2779d5b2b8 | ||
|
1daf078708 | ||
|
50003761c1 | ||
|
4ee4b0403e | ||
|
a0ca05e16d | ||
|
0771899e3f | ||
|
0995727374 | ||
|
cd0b3ce0c5 | ||
|
486e3f34d7 | ||
|
b80ad6ecf5 | ||
|
034f316d2c | ||
|
2bf041cf76 | ||
|
552bfce3ed | ||
|
ab0b79c114 | ||
|
15529d50a8 | ||
|
2acb068075 | ||
|
a9d555ff50 | ||
|
7e081d700b | ||
|
326d90e952 | ||
|
49a3b410f0 | ||
|
757b151601 | ||
|
719b525e2b | ||
|
b1a28624ba | ||
|
88e039efeb | ||
|
8b00644751 | ||
|
5dcae73657 | ||
|
8784dbbc74 | ||
|
c037dde536 | ||
|
2715e4bc98 | ||
|
c88ed31585 | ||
|
344796a6a8 | ||
|
122066ca6d | ||
|
80611111e9 | ||
|
22144a4fa3 | ||
|
bf23f7a2a5 | ||
|
fa619aaae8 | ||
|
764ceae1ef | ||
|
62ed1c813d | ||
|
ea9758a2ed | ||
|
8d00f6cdac | ||
|
43282855dd | ||
|
3ac9b6fbf0 | ||
|
adc2794ef6 | ||
|
a5bdbd57e2 | ||
|
d8113d497b | ||
|
ac0aab2fa0 | ||
|
0b4fa214b6 | ||
|
b89898ef7f | ||
|
4a36f0b085 | ||
|
3e0321f49c | ||
|
0c4342b461 | ||
|
d6903d0ff7 | ||
|
91515b09c4 | ||
|
59fdc3795b | ||
|
290ab8402b | ||
|
634a8b0c04 | ||
|
166f767767 | ||
|
8a96ec9c3a | ||
|
bee42dd5cc | ||
|
f4f897d3bf | ||
|
b580a112c1 | ||
|
dbd7e728b6 | ||
|
e3d8b3f2c3 | ||
|
b7a0264459 | ||
|
3229899a34 | ||
|
dc24dcd435 | ||
|
015c6af52d | ||
|
46998a9d21 | ||
|
47d57bfe78 | ||
|
4eb3afe8a4 | ||
|
6b96c19b01 | ||
|
870ae6be88 | ||
|
ab3ab92c15 | ||
|
13b376819c | ||
|
881236dc03 | ||
|
a173da91da | ||
|
76639ecf33 | ||
|
bf83911631 | ||
|
ce6e270a41 | ||
|
d9f95b77d4 | ||
|
cfc5d722ec | ||
|
d47f53518e | ||
|
8eaa91bf3b | ||
|
0d92eba476 | ||
|
776b4510c1 | ||
|
72b74820a9 | ||
|
30e80abe77 | ||
|
69113aad89 | ||
|
3bc4e88903 | ||
|
94c459970e | ||
|
e63ea6698e | ||
|
6292e2c04d | ||
|
c831deb81c | ||
|
5b36a556fe | ||
|
56034e7f2b | ||
|
056e29ea59 | ||
|
56fd559860 | ||
|
a01917baa2 | ||
|
bb3bc6da26 | ||
|
90da8af70f | ||
|
1ddf4c54cf | ||
|
563592aa3d | ||
|
27d357ed31 | ||
|
1d9957f14b | ||
|
6a0d838f33 | ||
|
054685fa67 | ||
|
b23dc4e961 | ||
|
55678a078a | ||
|
19b9a12e4f | ||
|
5a71336bd9 | ||
|
21aca082a9 | ||
|
66b77bfb6f | ||
|
1e6c5b75e3 | ||
|
ebed81099d | ||
|
7ca3407d30 | ||
|
ad4f1b9191 | ||
|
9e9aa997f1 |
77 changed files with 2578 additions and 1013 deletions
|
@ -33,19 +33,19 @@ schedules:
|
|||
variables:
|
||||
ICONV_VERSION: '1.16'
|
||||
# Use recent master libffi, because 3.3 is broken: checking host system type... Invalid configuration `arm-none-linux-eabi': machine `arm-none-linux' not recognized
|
||||
FFI_VERSION: 'dd5bd03075149d7cf8441875c1a344e8beb57dde'
|
||||
FFI_VERSION: '3.4.2'
|
||||
GETTEXT_VERSION: '0.21'
|
||||
#need to switch to meson build system to use a more recent version
|
||||
GLIB_VERSION: '2.58'
|
||||
GLIB_EXTRAVERSION: '3'
|
||||
GLIB_VERSION: '2.71'
|
||||
GLIB_EXTRAVERSION: '2'
|
||||
OBOE_VERSION: '1.5.0'
|
||||
SNDFILE_VERSION: '1.0.31'
|
||||
INSTPATCH_VERSION: '1.1.6'
|
||||
VORBIS_VERSION: '1.3.7'
|
||||
OGG_VERSION: '1.3.5'
|
||||
OPUS_VERSION: '1.3.1'
|
||||
# flac 1.3.3 is completely broken: pkgconfig is incorrectly installed, compilation failure, etc.; use recent master instead
|
||||
FLAC_VERSION: '27c615706cedd252a206dd77e3910dfa395dcc49'
|
||||
FLAC_VERSION: '1.3.4'
|
||||
PCRE_VERSION: '8.45'
|
||||
|
||||
# Android NDK sources and standalone toolchain is put here
|
||||
DEV: '$(System.DefaultWorkingDirectory)/android-build-root'
|
||||
|
@ -53,6 +53,7 @@ variables:
|
|||
# This is a symlink pointing to the real Android NDK
|
||||
# Must be the same as $ANDROID_NDK_HOME see:
|
||||
# https://github.com/actions/virtual-environments/blob/main/images/linux/Ubuntu2004-README.md
|
||||
# We cannot use $ANDROID_NDK_HOME because this is an environment variable, but here, we need a compile-time constant.
|
||||
NDK: '/usr/local/lib/android/sdk/ndk-bundle'
|
||||
|
||||
# All the built binaries, libs and their headers will be installed here
|
||||
|
@ -84,6 +85,7 @@ variables:
|
|||
CFLAGS: "-fPIE -fPIC -I$(PREFIX)/include --sysroot=$(NDK_TOOLCHAIN)/sysroot -I$(NDK_TOOLCHAIN)/sysroot/usr/include -Werror=implicit-function-declaration"
|
||||
CXXFLAGS: $(CFLAGS)
|
||||
CPPFLAGS: $(CXXFLAGS)
|
||||
DEBIAN_FRONTEND: 'noninteractive'
|
||||
|
||||
ARTIFACT_NAME: 'fluidsynth-android$(ANDROID_API)'
|
||||
|
||||
|
@ -96,30 +98,30 @@ jobs:
|
|||
ANDROID_ARCH: 'armv7a'
|
||||
ANDROID_ABI_CMAKE: 'armeabi-v7a'
|
||||
ANDROID_TARGET_ABI: "eabi"
|
||||
ANDROID_ABI_MESON: 'arm'
|
||||
# the --target to be used by autotools
|
||||
AUTOTOOLS_TARGET: "$(ARCH)-linux-android$(ANDROID_TARGET_ABI)"
|
||||
#AUTOTOOLS_TARGET: "$(ARCH)-none-linux-$(ANDROID_TARGET_ABI)"
|
||||
AARCH64:
|
||||
ARCH: 'aarch64'
|
||||
ANDROID_ARCH: 'aarch64'
|
||||
ANDROID_ABI_CMAKE: 'arm64-v8a'
|
||||
ANDROID_TARGET_ABI:
|
||||
ANDROID_ABI_MESON: 'aarch64'
|
||||
AUTOTOOLS_TARGET: "$(ARCH)-none-linux-android"
|
||||
#AUTOTOOLS_TARGET: "$(ARCH)-none-linux"
|
||||
i686:
|
||||
ARCH: 'i686'
|
||||
ANDROID_ARCH: 'i686'
|
||||
ANDROID_ABI_CMAKE: 'x86'
|
||||
ANDROID_TARGET_ABI:
|
||||
ANDROID_ABI_MESON: 'x86'
|
||||
AUTOTOOLS_TARGET: "$(ARCH)-pc-linux-android"
|
||||
#AUTOTOOLS_TARGET: "$(ARCH)-pc-linux"
|
||||
x86_64:
|
||||
ARCH: 'x86_64'
|
||||
ANDROID_ARCH: 'x86_64'
|
||||
ANDROID_ABI_CMAKE: 'x86_64'
|
||||
ANDROID_TARGET_ABI:
|
||||
ANDROID_ABI_MESON: 'x86_64'
|
||||
AUTOTOOLS_TARGET: "$(ARCH)-pc-linux-android"
|
||||
#AUTOTOOLS_TARGET: "$(ARCH)-pc-linux"
|
||||
|
||||
pool:
|
||||
vmImage: 'ubuntu-20.04'
|
||||
|
@ -130,13 +132,22 @@ jobs:
|
|||
mkdir -p $(DEV)
|
||||
displayName: 'mkdir $(DEV)'
|
||||
|
||||
- script: |
|
||||
sudo apt-get update -y
|
||||
displayName: 'Update apt'
|
||||
|
||||
- script: |
|
||||
set -ex
|
||||
sudo -E apt-get -y --no-install-suggests --no-install-recommends install wget tar bzip2 xz-utils ca-certificates
|
||||
displayName: 'apt-get install wget tar'
|
||||
|
||||
- script: |
|
||||
set -ex
|
||||
|
||||
wget http://ftp.gnu.org/pub/gnu/libiconv/libiconv-${ICONV_VERSION}.tar.gz
|
||||
tar zxf libiconv-${ICONV_VERSION}.tar.gz
|
||||
|
||||
wget -O libffi-${FFI_VERSION}.tar.gz https://github.com/libffi/libffi/archive/${FFI_VERSION}.tar.gz
|
||||
wget -O libffi-${FFI_VERSION}.tar.gz https://github.com/libffi/libffi/releases/download/v${FFI_VERSION}/libffi-${FFI_VERSION}.tar.gz
|
||||
tar zxf libffi-${FFI_VERSION}.tar.gz
|
||||
|
||||
wget http://ftp.gnu.org/pub/gnu/gettext/gettext-${GETTEXT_VERSION}.tar.gz
|
||||
|
@ -160,18 +171,25 @@ jobs:
|
|||
wget https://github.com/xiph/ogg/releases/download/v${OGG_VERSION}/libogg-${OGG_VERSION}.tar.gz
|
||||
tar zxf libogg-${OGG_VERSION}.tar.gz
|
||||
|
||||
wget -O flac-${FLAC_VERSION}.tar.gz https://github.com/xiph/flac/archive/${FLAC_VERSION}.tar.gz
|
||||
wget -O flac-${FLAC_VERSION}.tar.gz https://github.com/xiph/flac/archive/refs/tags/${FLAC_VERSION}.tar.gz
|
||||
tar xf flac-${FLAC_VERSION}.tar.gz
|
||||
|
||||
wget -O opus-${OPUS_VERSION}.tar.gz https://github.com/xiph/opus/archive/refs/tags/v${OPUS_VERSION}.tar.gz
|
||||
tar xf opus-${OPUS_VERSION}.tar.gz
|
||||
|
||||
wget -O pcre-${PCRE_VERSION}.tar.bz2 https://sourceforge.net/projects/pcre/files/pcre/${PCRE_VERSION}/pcre-${PCRE_VERSION}.tar.bz2/download
|
||||
tar jxf pcre-${PCRE_VERSION}.tar.bz2
|
||||
cd pcre-${PCRE_VERSION}
|
||||
# CMake checks for existence of strtoq() using the C compiler - and yes, it does exist!
|
||||
# Later on, it's actually used by the C++ compiler, where it does not exist.
|
||||
# Rename the function so CMake won't find it.
|
||||
sed -i 's/strtoq/strtoqqqq/g' CMakeLists.txt
|
||||
displayName: 'Download Dependencies'
|
||||
workingDirectory: $(DEV)
|
||||
|
||||
- task: Cache@2
|
||||
inputs:
|
||||
key: '$(ARCH) | $(DEV)/*.tar.gz | cacheVersion3'
|
||||
key: '$(ARCH) | $(DEV)/*.tar.*'
|
||||
path: '$(PREFIX)'
|
||||
cacheHitVar: 'CACHE_RESTORED'
|
||||
displayName: 'Cache fluidsynth dependency libraries'
|
||||
|
@ -184,19 +202,19 @@ jobs:
|
|||
wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | gpg --dearmor - | sudo tee /etc/apt/trusted.gpg.d/kitware.gpg >/dev/null
|
||||
sudo apt-add-repository 'deb https://apt.kitware.com/ubuntu/ focal main'
|
||||
displayName: 'Use recent CMake Version'
|
||||
condition: ne(variables.CACHE_RESTORED, 'true')
|
||||
condition: and(succeeded(), ne(variables.CACHE_RESTORED, 'true'))
|
||||
enabled: 'false'
|
||||
|
||||
- script: |
|
||||
sudo apt-get update -y
|
||||
displayName: 'Update apt'
|
||||
condition: ne(variables.CACHE_RESTORED, 'true')
|
||||
set -ex
|
||||
sudo -E apt-get -y --no-install-suggests --no-install-recommends install gettext cmake zlib1g-dev autogen automake autoconf libtool pkg-config autotools-dev build-essential meson ninja-build python3-distutils
|
||||
displayName: 'apt-get install build-tools'
|
||||
condition: and(succeeded(), ne(variables.CACHE_RESTORED, 'true'))
|
||||
|
||||
- script: |
|
||||
set -ex
|
||||
sudo -E apt-get -yq --no-install-suggests --no-install-recommends install gettext cmake zlib1g-dev autogen automake autoconf libtool pkg-config autotools-dev build-essential meson ninja-build
|
||||
displayName: 'apt-get install'
|
||||
condition: ne(variables.CACHE_RESTORED, 'true')
|
||||
ln -sfn $ANDROID_SDK_ROOT/ndk/21.4.7075529 $ANDROID_NDK_ROOT
|
||||
displayName: 'Use NDK r22'
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
|
@ -260,7 +278,15 @@ jobs:
|
|||
|
||||
displayName: 'Compile libiconv'
|
||||
workingDirectory: $(DEV)
|
||||
condition: ne(variables.CACHE_RESTORED, 'true')
|
||||
condition: and(succeeded(), ne(variables.CACHE_RESTORED, 'true'))
|
||||
|
||||
- script: |
|
||||
set -ex
|
||||
pushd libiconv-${ICONV_VERSION}
|
||||
cat config.log
|
||||
displayName: 'libiconv config.log'
|
||||
workingDirectory: $(DEV)
|
||||
condition: and(failed(), ne(variables.CACHE_RESTORED, 'true'))
|
||||
|
||||
- script: |
|
||||
set -ex
|
||||
|
@ -276,103 +302,7 @@ jobs:
|
|||
popd
|
||||
displayName: 'Compile libffi'
|
||||
workingDirectory: $(DEV)
|
||||
condition: ne(variables.CACHE_RESTORED, 'true')
|
||||
|
||||
- script: |
|
||||
set -ex
|
||||
export PKGCFG=`which pkg-config`
|
||||
pushd glib-${GLIB_VERSION}.${GLIB_EXTRAVERSION}
|
||||
|
||||
cat << EOF > cross-file.txt
|
||||
[host_machine]
|
||||
system = 'android'
|
||||
cpu_family = 'arm'
|
||||
cpu = 'arm'
|
||||
endian = 'little'
|
||||
|
||||
[binaries]
|
||||
c = '${CC}'
|
||||
cpp = '${CXX}'
|
||||
ar = '${AR}'
|
||||
ld = '${LD}'
|
||||
strip = '${STRIP}'
|
||||
pkgconfig = '${PKGCFG}'
|
||||
|
||||
[built-in options]
|
||||
c_std = 'c11'
|
||||
c_args = ['-fPIC','-I/home/git/work/ndk/builddir/out/include']
|
||||
cpp_args = ['-fPIC','-I/home/git/work/ndk/builddir/out/include']
|
||||
c_link_args = ['-fPIE','-L/home/git/work/ndk/builddir/out/lib']
|
||||
|
||||
pkg_config_path = '${PKG_CONFIG_PATH}'
|
||||
EOF
|
||||
|
||||
cat << EOF > native-file.txt
|
||||
[host_machine]
|
||||
system = 'linux'
|
||||
cpu_family = 'x86_64'
|
||||
cpu = 'x86_64'
|
||||
endian = 'little'
|
||||
|
||||
[properties]
|
||||
|
||||
[binaries]
|
||||
c = ['false']
|
||||
cpp = ['false']
|
||||
objc = ['false']
|
||||
objcpp = ['false']
|
||||
ar = ['false']
|
||||
pkgconfig = ['false']
|
||||
cmake = ['false']
|
||||
EOF
|
||||
|
||||
cat native-file.txt
|
||||
cat cross-file.txt
|
||||
|
||||
unset AR
|
||||
unset AS
|
||||
unset CC
|
||||
unset CFLAGS
|
||||
unset CPPFLAGS
|
||||
unset CPP
|
||||
unset CXXFLAGS
|
||||
unset CXX
|
||||
unset LDFLAGS
|
||||
unset LD
|
||||
unset STRIP
|
||||
|
||||
meson \
|
||||
--cross-file cross-file.txt \
|
||||
--native-file native-file.txt \
|
||||
--prefix=${PREFIX} \
|
||||
--libdir=lib \
|
||||
-Ddebug=false \
|
||||
--default-library=both \
|
||||
-Doptimization=s \
|
||||
--backend=ninja \
|
||||
--wrap-mode=nodownload \
|
||||
-Dinternal_pcre=true \
|
||||
-Dlibmount=false \
|
||||
-Ddtrace=false \
|
||||
-Diconv=auto \
|
||||
-Dxattr=false \
|
||||
-Dgtk_doc=false \
|
||||
_builddir \
|
||||
.
|
||||
ninja
|
||||
popd
|
||||
displayName: 'Compile glib (meson)'
|
||||
workingDirectory: $(DEV)
|
||||
enabled: 'false'
|
||||
|
||||
- script: |
|
||||
pushd glib-${GLIB_VERSION}.${GLIB_EXTRAVERSION}
|
||||
cat _builddir/meson-logs/meson-log.txt
|
||||
popd
|
||||
displayName: 'Meson LOG'
|
||||
workingDirectory: $(DEV)
|
||||
condition: failed()
|
||||
enabled: 'false'
|
||||
condition: and(succeeded(), ne(variables.CACHE_RESTORED, 'true'))
|
||||
|
||||
- script: |
|
||||
set -ex
|
||||
|
@ -400,96 +330,85 @@ jobs:
|
|||
popd
|
||||
displayName: 'Compile gettext'
|
||||
workingDirectory: $(DEV)
|
||||
condition: ne(variables.CACHE_RESTORED, 'true')
|
||||
condition: and(succeeded(), ne(variables.CACHE_RESTORED, 'true'))
|
||||
|
||||
- template: cmake-android.yml
|
||||
parameters:
|
||||
sourceDir: 'pcre-$(PCRE_VERSION)'
|
||||
cmakeArgs: '-DPCRE_SUPPORT_UNICODE_PROPERTIES=1 -DPCRE_SUPPORT_UTF=1 -DPCRE_BUILD_PCRECPP=0 -DPCRE_BUILD_TESTS=0'
|
||||
|
||||
- script: |
|
||||
set -ex
|
||||
|
||||
export PKGCFG=`which pkg-config`
|
||||
pushd glib-${GLIB_VERSION}.${GLIB_EXTRAVERSION}
|
||||
cat << EOF > android.cache
|
||||
glib_cv_long_long_format=ll
|
||||
glib_cv_stack_grows=no
|
||||
glib_cv_sane_realloc=yes
|
||||
glib_cv_have_strlcpy=no
|
||||
glib_cv_va_val_copy=yes
|
||||
glib_cv_rtldglobal_broken=no
|
||||
glib_cv_uscore=no
|
||||
glib_cv_monotonic_clock=no
|
||||
ac_cv_func_nonposix_getpwuid_r=no
|
||||
ac_cv_func_posix_getpwuid_r=no
|
||||
ac_cv_func_posix_getgrgid_r=no
|
||||
glib_cv_use_pid_surrogate=yes
|
||||
ac_cv_func_printf_unix98=no
|
||||
ac_cv_func_vsnprintf_c99=yes
|
||||
ac_cv_func_realloc_0_nonnull=yes
|
||||
ac_cv_func_realloc_works=yes
|
||||
|
||||
cat << EOF > cross_file.ini
|
||||
[host_machine]
|
||||
system = 'android'
|
||||
cpu_family = '${ANDROID_ABI_MESON}'
|
||||
cpu = '${ANDROID_ARCH}'
|
||||
endian = 'little'
|
||||
|
||||
[binaries]
|
||||
c = '${NDK_TOOLCHAIN}/bin/${CC}'
|
||||
cpp = '${NDK_TOOLCHAIN}/bin/${CXX}'
|
||||
ar = '${NDK_TOOLCHAIN}/bin/${AR}'
|
||||
as = '${NDK_TOOLCHAIN}/bin/${AS}'
|
||||
ld = '${NDK_TOOLCHAIN}/bin/${LD}'
|
||||
strip = '${NDK_TOOLCHAIN}/bin/${STRIP}'
|
||||
ranlib = '${NDK_TOOLCHAIN}/bin/${RANLIB}'
|
||||
pkgconfig = '${PKGCFG}'
|
||||
|
||||
[properties]
|
||||
prefix = '${PREFIX}'
|
||||
c_args = '${CFLAGS}'
|
||||
cpp_args = '${CXXFLAGS}'
|
||||
pkg_config_libdir = '${PKG_CONFIG_LIBDIR}'
|
||||
c_link_args = '${LDFLAGS}'
|
||||
|
||||
[project options]
|
||||
libmount = 'disabled'
|
||||
xattr = false
|
||||
selinux = 'disabled'
|
||||
nls = 'disabled'
|
||||
glib_debug = 'disabled'
|
||||
glib_assert = false
|
||||
glib_checks = false
|
||||
libelf = 'disabled'
|
||||
EOF
|
||||
|
||||
# Unfortunately, libffi is not linked against libgobject when compiling for aarch64, leading to the following error:
|
||||
#
|
||||
# /bin/bash ../libtool --tag=CC --mode=link aarch64-linux-android23-clang -Wall -Wstrict-prototypes -Wno-bad-function-cast -Werror=declaration-after-statement -Werror=missing-prototypes -Werror=implicit-function-declaration -Werror=pointer-arith -Werror=init-self -Werror=format=2 -Werror=missing-include-dirs -fPIE -fPIC -I/home/vsts/work/1/s/android-build-root/opt/android/include --sysroot=/usr/local/lib/android/sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64//sysroot -I/usr/local/lib/android/sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64//sysroot/include -Werror=implicit-function-declaration -fno-integrated-as -fno-strict-aliasing -pie -Wl,-rpath-link=-I/usr/local/lib/android/sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64//sysroot/usr/lib -L/usr/local/lib/android/sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64//sysroot/usr/lib -L/home/vsts/work/1/s/android-build-root/opt/android/lib -L/usr/local/lib/android/sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64//lib -o gobject-query gobject-query.o ./libgobject-2.0.la ../glib/libglib-2.0.la -lintl -liconv
|
||||
# libtool: link: aarch64-linux-android23-clang -Wall -Wstrict-prototypes -Wno-bad-function-cast -Werror=declaration-after-statement -Werror=missing-prototypes -Werror=implicit-function-declaration -Werror=pointer-arith -Werror=init-self -Werror=format=2 -Werror=missing-include-dirs -fPIE -fPIC -I/home/vsts/work/1/s/android-build-root/opt/android/include --sysroot=/usr/local/lib/android/sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64//sysroot -I/usr/local/lib/android/sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64//sysroot/include -Werror=implicit-function-declaration -fno-integrated-as -fno-strict-aliasing -pie -Wl,-rpath-link=-I/usr/local/lib/android/sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64//sysroot/usr/lib -o .libs/gobject-query gobject-query.o -L/usr/local/lib/android/sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64//sysroot/usr/lib -L/home/vsts/work/1/s/android-build-root/opt/android/lib -L/usr/local/lib/android/sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64//lib ./.libs/libgobject-2.0.so ../glib/.libs/libglib-2.0.so /home/vsts/work/1/s/android-build-root/opt/android/lib/libintl.so /home/vsts/work/1/s/android-build-root/opt/android/lib/libiconv.so -pthread -L/home/vsts/work/1/s/android-build-root/opt/android/lib
|
||||
# /usr/local/lib/android/sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64//bin/../lib/gcc/aarch64-linux-android/4.9.x/../../../../aarch64-linux-android/bin/ld: warning: libffi.so, needed by ./.libs/libgobject-2.0.so, not found (try using -rpath or -rpath-link)
|
||||
# ./.libs/libgobject-2.0.so: undefined reference to `ffi_type_sint32@LIBFFI_BASE_8.0'
|
||||
# ./.libs/libgobject-2.0.so: undefined reference to `ffi_prep_cif@LIBFFI_BASE_8.0'
|
||||
#
|
||||
# So, just add it to LDFLAGS to make sure it's always linked.
|
||||
# libz.so is also missing...
|
||||
#FFILIB=`pkg-config --libs libffi`
|
||||
#echo ${FFILIB}
|
||||
#export LDFLAGS="${LDFLAGS} ${FFILIB} -lz"
|
||||
#unset FFILIB
|
||||
cat cross_file.ini
|
||||
|
||||
chmod a-x android.cache
|
||||
NOCONFIGURE=true ./autogen.sh
|
||||
./configure \
|
||||
--host=${ANDROID_TARGET} \
|
||||
--prefix=${PREFIX} \
|
||||
--libdir=${LIBPATH0} \
|
||||
--disable-dependency-tracking \
|
||||
--cache-file=android.cache \
|
||||
--enable-included-printf \
|
||||
--with-pcre=no \
|
||||
--enable-libmount=no \
|
||||
--enable-xattr=no \
|
||||
--with-libiconv=gnu \
|
||||
--disable-static \
|
||||
--enable-shared \
|
||||
--with-pic \
|
||||
--disable-maintainer-mode \
|
||||
--disable-silent-rules
|
||||
make -j$((`nproc`+1))
|
||||
make install
|
||||
# When CC and CXX are set, then meson detects them as host compiler (not cross compiler),
|
||||
# so they tries to run arm binaries in x86. That's why sanity check is failing, and that's
|
||||
# why we have to use env -i.
|
||||
# And we must explicitly set PKG_CONFIG_LIBDIR, because pkg_config_libdir is only recognized by meson >= 0.54
|
||||
env -i bash -c "export PATH && export PKG_CONFIG_LIBDIR=$(PKG_CONFIG_LIBDIR) && meson setup build --cross-file cross_file.ini --prefix=$(PREFIX)"
|
||||
ninja -C build
|
||||
ninja -C build install
|
||||
popd
|
||||
displayName: 'Compile glib'
|
||||
displayName: 'Compile glib (meson)'
|
||||
workingDirectory: $(DEV)
|
||||
condition: ne(variables.CACHE_RESTORED, 'true')
|
||||
condition: and(succeeded(), ne(variables.CACHE_RESTORED, 'true'))
|
||||
|
||||
- script: |
|
||||
pushd glib-${GLIB_VERSION}.${GLIB_EXTRAVERSION}
|
||||
ls -la build
|
||||
cat build/meson-logs/meson-log.txt
|
||||
popd
|
||||
displayName: 'Meson LOG'
|
||||
workingDirectory: $(DEV)
|
||||
condition: and(succeededOrFailed(), ne(variables.CACHE_RESTORED, 'true'))
|
||||
|
||||
- template: cmake-android.yml
|
||||
parameters:
|
||||
sourceDir: 'libogg-$(OGG_VERSION)'
|
||||
cmakeArgs: '-DINSTALL_DOCS=0'
|
||||
|
||||
- script: |
|
||||
ls -la libogg-${OGG_VERSION}/build/CMakeFiles/
|
||||
cat libogg-${OGG_VERSION}/build/CMakeFiles/CMakeError.log
|
||||
true
|
||||
displayName: 'Print OGG Cmake Error Log'
|
||||
condition: always()
|
||||
workingDirectory: $(DEV)
|
||||
|
||||
- template: cmake-android.yml
|
||||
parameters:
|
||||
sourceDir: 'libvorbis-$(VORBIS_VERSION)'
|
||||
|
||||
- script: |
|
||||
ls -la libvorbis-${VORBIS_VERSION}/build/CMakeFiles/
|
||||
cat libvorbis-${VORBIS_VERSION}/build/CMakeFiles/CMakeError.log
|
||||
true
|
||||
displayName: 'Print Vorbis Cmake Error Log'
|
||||
condition: always()
|
||||
workingDirectory: $(DEV)
|
||||
|
||||
# flac uses c99 macros, but doesnt specify a standard, so we need to do it explicitly.
|
||||
# On i686, they invoke yasm with -fstack-protector-strong flag... turn off asm optimizations.
|
||||
- template: cmake-android.yml
|
||||
|
@ -497,42 +416,17 @@ jobs:
|
|||
sourceDir: 'flac-$(FLAC_VERSION)'
|
||||
cmakeArgs: '-DCMAKE_C_STANDARD=99 -DCMAKE_C_STANDARD_REQUIRED=1 -DWITH_ASM=0 -DBUILD_CXXLIBS=0 -DBUILD_PROGRAMS=0 -DBUILD_EXAMPLES=0 -DBUILD_DOCS=0 -DINSTALL_MANPAGES=0'
|
||||
|
||||
- script: |
|
||||
ls -la flac-${FLAC_VERSION}/build/CMakeFiles/
|
||||
cat flac-${FLAC_VERSION}/build/CMakeFiles/CMakeError.log
|
||||
true
|
||||
displayName: 'Print FLAC Cmake Error Log'
|
||||
condition: always()
|
||||
workingDirectory: $(DEV)
|
||||
|
||||
# another broken xiph project that doesn't specify the C standard and keeps complaining of you don't have C99
|
||||
- template: cmake-android.yml
|
||||
parameters:
|
||||
sourceDir: 'opus-$(OPUS_VERSION)'
|
||||
cmakeArgs: '-DBUILD_PROGRAMS=0 -DOPUS_MAY_HAVE_NEON=1 -DCMAKE_C_STANDARD=99 -DCMAKE_C_STANDARD_REQUIRED=1'
|
||||
|
||||
- script: |
|
||||
ls -la opus-${OPUS_VERSION}/build/CMakeFiles/
|
||||
cat opus-${OPUS_VERSION}/build/CMakeFiles/CMakeError.log
|
||||
cat opus-${OPUS_VERSION}/build/CMakeFiles/CMakeOutput.log
|
||||
true
|
||||
displayName: 'Print OPUS Cmake Error Log'
|
||||
condition: always()
|
||||
workingDirectory: $(DEV)
|
||||
|
||||
- template: cmake-android.yml
|
||||
parameters:
|
||||
sourceDir: 'libsndfile-$(SNDFILE_VERSION)'
|
||||
cmakeArgs: '-DBUILD_PROGRAMS=0 -DBUILD_EXAMPLES=0'
|
||||
|
||||
- script: |
|
||||
ls -la libsndfile-${SNDFILE_VERSION}/build/CMakeFiles/
|
||||
cat libsndfile-${SNDFILE_VERSION}/build/CMakeFiles/CMakeError.log
|
||||
true
|
||||
displayName: 'Print libsndfile Cmake Error Log'
|
||||
condition: always()
|
||||
workingDirectory: $(DEV)
|
||||
|
||||
- template: cmake-android.yml
|
||||
parameters:
|
||||
sourceDir: 'oboe-$(OBOE_VERSION)'
|
||||
|
@ -559,7 +453,7 @@ jobs:
|
|||
|
||||
displayName: 'Create fake oboe.pc'
|
||||
workingDirectory: $(DEV)
|
||||
condition: ne(variables.CACHE_RESTORED, 'true')
|
||||
condition: and(succeeded(), ne(variables.CACHE_RESTORED, 'true'))
|
||||
|
||||
- template: cmake-android.yml
|
||||
parameters:
|
||||
|
@ -598,12 +492,11 @@ jobs:
|
|||
sourceDir: '.'
|
||||
condition: succeeded()
|
||||
installCommand: 'cp *.so ${PREFIX}/lib/'
|
||||
|
||||
|
||||
- script: |
|
||||
ls -Rg $(PREFIX)
|
||||
displayName: 'Show cross-compiled files in $(PREFIX)'
|
||||
condition: always()
|
||||
condition: or(succeeded(), failed())
|
||||
|
||||
- script: |
|
||||
set -ex
|
||||
|
@ -637,6 +530,8 @@ jobs:
|
|||
ls libvorbis.so
|
||||
ls libvorbisenc.so
|
||||
ls libvorbisfile.so
|
||||
ls libpcre.so
|
||||
ls libpcreposix.so
|
||||
displayName: 'Verify all libs exist'
|
||||
workingDirectory: '$(PREFIX)/lib'
|
||||
|
||||
|
|
|
@ -13,16 +13,28 @@ trigger:
|
|||
- '.cirrus.yml'
|
||||
- 'README.md'
|
||||
|
||||
parameters:
|
||||
- name: UseCache
|
||||
displayName: Use Dependency Cache
|
||||
type: boolean
|
||||
default: true
|
||||
|
||||
jobs:
|
||||
- job: macOS
|
||||
- job: macOS_brew
|
||||
strategy:
|
||||
matrix:
|
||||
10_14:
|
||||
imageName: 'macOS-10.14'
|
||||
UnixLibs:
|
||||
imageName: 'macos-11'
|
||||
CMakeFlags: '-Denable-framework=0'
|
||||
10_15:
|
||||
imageName: 'macOS-10.15'
|
||||
CMakeFlags: ''
|
||||
11_0:
|
||||
imageName: 'macos-11'
|
||||
CMakeFlags: ''
|
||||
12_0:
|
||||
imageName: 'macos-12'
|
||||
CMakeFlags: ''
|
||||
|
||||
pool:
|
||||
vmImage: $(imageName)
|
||||
|
@ -39,11 +51,149 @@ jobs:
|
|||
set -ex
|
||||
mkdir build && cd build
|
||||
export PKG_CONFIG_PATH="/usr/local/opt/libffi/lib/pkgconfig"
|
||||
cmake -Werror=dev -DCMAKE_INSTALL_PREFIX=$(Build.ArtifactStagingDirectory) -DCMAKE_BUILD_TYPE=Release -DCMAKE_VERBOSE_MAKEFILE=1 -DNO_GUI=1 ..
|
||||
cmake -Werror=dev $(CMakeFlags) -DCMAKE_BUILD_TYPE=Release -DCMAKE_VERBOSE_MAKEFILE=1 -DNO_GUI=1 ..
|
||||
make -j3
|
||||
displayName: 'Compile fluidsynth'
|
||||
- script: |
|
||||
set -ex
|
||||
cd build || exit -1
|
||||
make -j3 check || exit -1
|
||||
cd build
|
||||
make -j3 check
|
||||
displayName: 'Execute Unittests'
|
||||
- script: |
|
||||
set -ex
|
||||
cd build
|
||||
make -j3 demo
|
||||
displayName: 'Compile demos'
|
||||
- script: |
|
||||
set -ex
|
||||
cd build
|
||||
sudo make install
|
||||
rm -f install_manifest.txt
|
||||
displayName: 'Install fluidsynth to default location'
|
||||
- script: |
|
||||
set -ex
|
||||
cd build
|
||||
cmake -DCMAKE_INSTALL_PREFIX=$(Build.ArtifactStagingDirectory) ..
|
||||
make install
|
||||
displayName: 'Install fluidsynth to artifact dir'
|
||||
|
||||
|
||||
- job: macOS_ports
|
||||
timeoutInMinutes: 300
|
||||
strategy:
|
||||
matrix:
|
||||
# SDL2/SDL_cpuinfo.h includes some x86 specific headers, which ofc doesn't work when cross compiling for arm64
|
||||
# And this universal build thingy doesn't work on Mac10.15 for some reason...
|
||||
# Furthermore, there is a problem when restoring the cache on Mac11, so disable this job as well
|
||||
#11_0_universal_unixlibs:
|
||||
# macPortsUrl: 'https://github.com/macports/macports-base/releases/download/v2.7.2/MacPorts-2.7.2-11-BigSur.pkg'
|
||||
# imageName: 'macos-11'
|
||||
# CMakeFlags: '-Denable-sdl2=0 -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" -Denable-framework=0 -DLIB_SUFFIX=""'
|
||||
12_0_universal_unixlibs:
|
||||
macPortsUrl: 'https://github.com/macports/macports-base/releases/download/v2.7.2/MacPorts-2.7.2-12-Monterey.pkg'
|
||||
imageName: 'macos-12'
|
||||
CMakeFlags: '-Denable-sdl2=0 -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" -Denable-framework=0 -DLIB_SUFFIX=""'
|
||||
pool:
|
||||
vmImage: $(imageName)
|
||||
steps:
|
||||
- script: |
|
||||
set -ex
|
||||
brew install wget pkg-config
|
||||
wget $(macPortsUrl)
|
||||
sudo installer -pkg *.pkg -target /
|
||||
rm -f *.pkg
|
||||
sudo chown -R $(id -u):$(id -g) /opt/local
|
||||
sudo chflags nouchg /opt/local
|
||||
displayName: 'Prerequisites'
|
||||
workingDirectory: $(Agent.TempDirectory)
|
||||
- task: Cache@2
|
||||
continueOnError: true
|
||||
displayName: "Cache macPort packages"
|
||||
condition: and(not(in(variables['Build.Reason'], 'Schedule')), ${{ parameters.useCache }})
|
||||
inputs:
|
||||
key: '"$(Agent.OS)" | "$(imageName)" | "$(macPortsUrl)" | "versionalways"'
|
||||
path: '/opt/local'
|
||||
cacheHitVar: CACHE_RESTORED
|
||||
- script: |
|
||||
set -ex
|
||||
export PATH=$PATH:/opt/local/bin
|
||||
echo $PATH
|
||||
which codesign
|
||||
which port
|
||||
cmake --version || true
|
||||
|
||||
echo "+universal" | sudo tee -a /opt/local/etc/macports/variants.conf
|
||||
|
||||
sudo sh -c 'cat << EOF >> /opt/local/etc/macports/macports.conf
|
||||
buildfromsource always
|
||||
universal_archs arm64 x86_64
|
||||
ui_interactive no
|
||||
EOF'
|
||||
|
||||
sudo port install glib2-devel libsndfile dbus-glib readline
|
||||
# fixup permissions to allow non-priv pipeline user access every directory, to make the caching step succeed at the end
|
||||
sudo chown -R $(id -u):$(id -g) /opt/local
|
||||
# remove all extended attributes, as they cannot be restored when restoring the pipeline cache
|
||||
#sudo xattr -rcv /opt/local
|
||||
displayName: 'Port install universal'
|
||||
condition: and(succeeded(), ne(variables.CACHE_RESTORED, 'true'))
|
||||
- script: |
|
||||
set -ex
|
||||
export PATH=$PATH:/opt/local/bin
|
||||
export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig"
|
||||
mkdir build && cd build
|
||||
cmake -Werror=dev $(CMakeFlags) -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_VERBOSE_MAKEFILE=1 -DNO_GUI=1 ..
|
||||
make -j3
|
||||
displayName: 'Compile fluidsynth'
|
||||
- script: |
|
||||
export PATH=$PATH:/opt/local/bin
|
||||
sudo port -v install fluidsynth +universal
|
||||
displayName: 'port install fluidsynth +universal'
|
||||
condition: failed()
|
||||
enabled: false
|
||||
- script: |
|
||||
set -x
|
||||
cat /opt/local/var/macports/logs/*cmake-bootstrap/cmake-bootstrap/main.log
|
||||
cat /opt/local/var/macports/build/*cmake-bootstrap/cmake-bootstrap/work/cmake-3.9.4-arm64/Bootstrap.cmk/*.log
|
||||
cat /opt/local/var/macports/logs/*_fluidsynth/fluidsynth/main.log
|
||||
condition: failed()
|
||||
displayName: 'Print fluidsynth error log'
|
||||
- script: |
|
||||
set -ex
|
||||
cd build
|
||||
make -j3 check
|
||||
displayName: 'Execute Unittests'
|
||||
- script: |
|
||||
set -ex
|
||||
cd build
|
||||
make -j3 demo
|
||||
displayName: 'Compile demos'
|
||||
- script: |
|
||||
set -ex
|
||||
cd build
|
||||
sudo make install
|
||||
rm -f install_manifest.txt
|
||||
displayName: 'Install fluidsynth to default location'
|
||||
- script: |
|
||||
set -ex
|
||||
cd build
|
||||
cmake -DCMAKE_INSTALL_PREFIX=$(Build.ArtifactStagingDirectory) ..
|
||||
make install
|
||||
cd /opt/local/lib/
|
||||
cp -a libgthread*.dylib libglib*.dylib libintl*.dylib libsndfile*.dylib libdbus-*.dylib libreadline*.dylib $(Build.ArtifactStagingDirectory)/lib
|
||||
file /opt/local/lib/libglib-2.0.dylib $(Build.ArtifactStagingDirectory)/bin/fluidsynth $(Build.ArtifactStagingDirectory)/lib/libfluidsynth*.dylib
|
||||
displayName: 'Install fluidsynth to artifact dir'
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: 'Publish fluidsynth artifacts'
|
||||
inputs:
|
||||
PathtoPublish: '$(Build.ArtifactStagingDirectory)'
|
||||
ArtifactName: 'fluidsynth-$(imageName)'
|
||||
publishLocation: 'Container'
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: 'Publish macPorts deps'
|
||||
enabled: false
|
||||
condition: and(succeeded(), ne(variables.CACHE_RESTORED, 'true'))
|
||||
inputs:
|
||||
PathtoPublish: '/opt/local/lib'
|
||||
ArtifactName: 'macports-$(imageName)'
|
||||
publishLocation: 'Container'
|
||||
|
|
|
@ -31,7 +31,7 @@ variables:
|
|||
toolset: 'v142'
|
||||
generator: 'Visual Studio 16 2019'
|
||||
configuration: 'RelWithDebInfo'
|
||||
VCPKG_REVISION: 'e6dcc079c81161786eb7b052209a2047e79f2c6c'
|
||||
VCPKG_REVISION: 'e809a42f87565e803b2178a0c11263f462d1800a'
|
||||
|
||||
jobs:
|
||||
- job: vcpkg
|
||||
|
@ -69,17 +69,17 @@ jobs:
|
|||
# ninja --version
|
||||
cmake --version
|
||||
rm -rf C:/Strawberry/perl/bin/pkg-config*
|
||||
choco install --svc --sdc -i pkgconfiglite &
|
||||
chocoTask=$!
|
||||
choco install --svc --sdc -i pkgconfiglite
|
||||
# chocoTask=$!
|
||||
# manually update vcpkg
|
||||
cd $VCPKG_INSTALLATION_ROOT
|
||||
# git checkout master
|
||||
git remote -v
|
||||
git fetch --unshallow --tags --prune --progress origin
|
||||
git fetch --tags --prune --progress origin
|
||||
git checkout --force $(VCPKG_REVISION)
|
||||
sed -i 's/arm64/arm/g' ports/glib/portfile.cmake
|
||||
./bootstrap-vcpkg.sh
|
||||
wait $chocoTask
|
||||
# wait $chocoTask
|
||||
which pkg-config
|
||||
displayName: 'Update vcpkg'
|
||||
- task: DownloadBuildArtifacts@0
|
||||
|
@ -126,6 +126,10 @@ jobs:
|
|||
cmake --build build --config $(configuration) --target check --parallel 3
|
||||
displayName: 'Execute Unittests'
|
||||
condition: and(succeeded(), and(ne(variables['platform'], 'arm'), ne(variables['platform'], 'arm64')))
|
||||
- bash: |
|
||||
set -ex
|
||||
cmake --build build --config $(configuration) --target demo --parallel 3
|
||||
displayName: 'Compile demos'
|
||||
- script: |
|
||||
@ECHO ON
|
||||
cd build
|
||||
|
|
|
@ -24,11 +24,15 @@ jobs:
|
|||
gtk-bundle: $(gtk-bundle-x86)
|
||||
libsndfile-url: $(libsndfile-url-x86)
|
||||
artifact-prefix: "fluidsynth"
|
||||
CFLAGS: "/arch:IA32"
|
||||
CXXFLAGS: "/arch:IA32"
|
||||
x64:
|
||||
platform: x64
|
||||
gtk-bundle: $(gtk-bundle-x64)
|
||||
libsndfile-url: $(libsndfile-url-x64)
|
||||
artifact-prefix: "fluidsynth"
|
||||
CFLAGS: ""
|
||||
CXXFLAGS: ""
|
||||
pool:
|
||||
vmImage: 'windows-2019'
|
||||
steps:
|
||||
|
@ -38,7 +42,7 @@ jobs:
|
|||
# https://dev.azure.com/tommbrt/_apis/projects?api-version=5.0
|
||||
project: 'd3638885-de4a-4ce7-afe7-f237ae461c07'
|
||||
pipeline: 1
|
||||
artifactName: libinstpatch-$(platform)
|
||||
artifactName: libinstpatch-XP-$(platform)
|
||||
downloadPath: '$(Build.ArtifactStagingDirectory)'
|
||||
displayName: 'Get libinstpatch'
|
||||
- script: |
|
||||
|
@ -52,11 +56,11 @@ jobs:
|
|||
REM need to fix the naming of libsndfile otherwise the linker won't find it
|
||||
mv lib\libsndfile-1.lib lib\sndfile.lib || exit -1
|
||||
mv lib\libsndfile-1.def lib\sndfile.def || exit -1
|
||||
cd $(Build.ArtifactStagingDirectory)\libinstpatch-$(platform)
|
||||
cd $(Build.ArtifactStagingDirectory)\libinstpatch-XP-$(platform)
|
||||
cp -rf * d:\deps\
|
||||
mv -f * ..
|
||||
cd ..
|
||||
rmdir $(Build.ArtifactStagingDirectory)\libinstpatch-$(platform)\
|
||||
rmdir $(Build.ArtifactStagingDirectory)\libinstpatch-XP-$(platform)\
|
||||
DEL /F C:\Strawberry\perl\bin\pkg-config.bat
|
||||
displayName: 'Prerequisites'
|
||||
- script: |
|
||||
|
@ -73,6 +77,12 @@ jobs:
|
|||
cd build || exit -1
|
||||
cmake --build . --config Release --target check || exit -1
|
||||
displayName: 'Execute Unittests'
|
||||
- script: |
|
||||
@ECHO ON
|
||||
SET "PATH=d:\deps\bin;%PATH%"
|
||||
cd build || exit -1
|
||||
cmake --build . --config Release --target demo || exit -1
|
||||
displayName: 'Compile demos'
|
||||
- script: |
|
||||
@ECHO ON
|
||||
cd build
|
||||
|
@ -140,6 +150,12 @@ jobs:
|
|||
cd build || exit -1
|
||||
cmake --build . --config $(CMAKE_CONFIG) --target check || exit -1
|
||||
displayName: 'Execute Unittests'
|
||||
- script: |
|
||||
@ECHO ON
|
||||
SET "PATH=d:\deps\bin;%PATH%"
|
||||
cd build || exit -1
|
||||
cmake --build . --config $(CMAKE_CONFIG) --target demo || exit -1
|
||||
displayName: 'Compile demos'
|
||||
|
||||
- job: WindowsMinGW
|
||||
variables:
|
||||
|
@ -208,6 +224,15 @@ jobs:
|
|||
cd build || exit -1
|
||||
mingw32-make.exe -j4 check || exit -1
|
||||
displayName: 'Execute Unittests'
|
||||
- script: |
|
||||
@ECHO ON
|
||||
SET "PATH=d:\deps\bin;%PATH%"
|
||||
REM remove that path from PATH to make sure sh.exe is not found (cmake will complain otherwise)
|
||||
set PATH=%PATH:C:\Program Files\Git\bin;=%
|
||||
set PATH=%PATH:C:\Program Files\Git\usr\bin;=%
|
||||
cd build || exit -1
|
||||
mingw32-make.exe -j4 demo || exit -1
|
||||
displayName: 'Compile demos'
|
||||
- script: |
|
||||
@ECHO ON
|
||||
cd build
|
||||
|
|
|
@ -11,7 +11,7 @@ parameters:
|
|||
default: $(DEV)
|
||||
- name: condition
|
||||
type: string
|
||||
default: ne(variables.CACHE_RESTORED, 'true')
|
||||
default: and(succeeded(), ne(variables.CACHE_RESTORED, 'true'))
|
||||
- name: installCommand
|
||||
type: string
|
||||
default: 'make install'
|
||||
|
@ -56,3 +56,12 @@ steps:
|
|||
displayName: 'Compile ${{ parameters.sourceDir }}'
|
||||
workingDirectory: ${{ parameters.workDir }}
|
||||
condition: ${{ parameters.condition }}
|
||||
|
||||
- script: |
|
||||
ls -la ${{ parameters.sourceDir }}/build/CMakeFiles/
|
||||
cat ${{ parameters.sourceDir }}/build/CMakeFiles/CMakeError.log
|
||||
cat ${{ parameters.sourceDir }}/build/CMakeFiles/CMakeOutput.log
|
||||
true
|
||||
displayName: 'Print ${{ parameters.sourceDir }} Cmake Error Log'
|
||||
condition: or(${{ parameters.condition }}, failed())
|
||||
workingDirectory: ${{ parameters.workDir }}
|
||||
|
|
6
.github/workflows/linux.yml
vendored
6
.github/workflows/linux.yml
vendored
|
@ -62,7 +62,6 @@ jobs:
|
|||
echo Can execute `nproc` make jobs in parallel
|
||||
cmake --version
|
||||
cmake -E make_directory ${{github.workspace}}/build
|
||||
sudo ln -s /usr/bin/clang-tidy-10 /usr/bin/clang-tidy
|
||||
which clang-tidy || true
|
||||
ls -la `which clang-tidy` || true
|
||||
echo $PATH
|
||||
|
@ -93,6 +92,11 @@ jobs:
|
|||
# Execute tests defined by the CMake configuration.
|
||||
run: make -j`nproc` check
|
||||
|
||||
- name: Demo
|
||||
working-directory: ${{github.workspace}}/build
|
||||
shell: bash
|
||||
run: make -j`nproc` demo
|
||||
|
||||
- name: Install
|
||||
working-directory: ${{github.workspace}}/build
|
||||
run: make install
|
||||
|
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,4 +1,5 @@
|
|||
build/
|
||||
.vs/
|
||||
|
||||
CMakeCache.txt
|
||||
CMakeFiles
|
||||
|
|
|
@ -3,3 +3,4 @@ workflow:
|
|||
- branch_package:
|
||||
source_project: home:derselbst:anmp
|
||||
source_package: fluidsynth
|
||||
target_project: home:derselbst:anmp:github-ci
|
||||
|
|
582
CMakeLists.txt
582
CMakeLists.txt
|
@ -1,6 +1,6 @@
|
|||
# FluidSynth - A Software Synthesizer
|
||||
#
|
||||
# Copyright (C) 2003-2021 Peter Hanappe and others.
|
||||
# Copyright (C) 2003-2022 Peter Hanappe and others.
|
||||
#
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public License
|
||||
|
@ -19,18 +19,21 @@
|
|||
|
||||
# CMake based build system. Pedro Lopez-Cabanillas <plcl@users.sf.net>
|
||||
|
||||
cmake_minimum_required ( VERSION 3.1.0 ) # because of CMAKE_C_STANDARD
|
||||
cmake_minimum_required ( VERSION 3.13 )
|
||||
# 3.1 because of CMAKE_C_STANDARD
|
||||
# 3.11 because COMPATIBILITY SameMinorVersion in CMakePackageConfigHelpers
|
||||
# 3.13.5 because it is the latest supported in Windows XP
|
||||
|
||||
if(POLICY CMP0075)
|
||||
if(POLICY CMP0075) # CMake version 3.13.5 warns when the policy is not set or value is OLD
|
||||
cmake_policy(SET CMP0075 NEW)
|
||||
endif()
|
||||
|
||||
if(POLICY CMP0091)
|
||||
if(POLICY CMP0091) # new in CMake 3.15, defaults to OLD
|
||||
cmake_policy(SET CMP0091 NEW)
|
||||
endif()
|
||||
|
||||
project ( FluidSynth C CXX )
|
||||
list( APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake_admin )
|
||||
list( APPEND CMAKE_MODULE_PATH ${FluidSynth_SOURCE_DIR}/cmake_admin )
|
||||
|
||||
# FluidSynth package name
|
||||
set ( PACKAGE "fluidsynth" )
|
||||
|
@ -38,7 +41,7 @@ set ( PACKAGE "fluidsynth" )
|
|||
# FluidSynth package version
|
||||
set ( FLUIDSYNTH_VERSION_MAJOR 2 )
|
||||
set ( FLUIDSYNTH_VERSION_MINOR 2 )
|
||||
set ( FLUIDSYNTH_VERSION_MICRO 4 )
|
||||
set ( FLUIDSYNTH_VERSION_MICRO 8 )
|
||||
set ( VERSION "${FLUIDSYNTH_VERSION_MAJOR}.${FLUIDSYNTH_VERSION_MINOR}.${FLUIDSYNTH_VERSION_MICRO}" )
|
||||
set ( FLUIDSYNTH_VERSION "\"${VERSION}\"" )
|
||||
|
||||
|
@ -52,20 +55,22 @@ set ( FLUIDSYNTH_VERSION "\"${VERSION}\"" )
|
|||
# if any interfaces have been removed/changed (compatibility broken): AGE=0
|
||||
# This is not exactly the same algorithm as the libtool one, but the results are the same.
|
||||
set ( LIB_VERSION_CURRENT 3 )
|
||||
set ( LIB_VERSION_AGE 0 )
|
||||
set ( LIB_VERSION_REVISION 4 )
|
||||
set ( LIB_VERSION_AGE 1 )
|
||||
set ( LIB_VERSION_REVISION 1 )
|
||||
set ( LIB_VERSION_INFO
|
||||
"${LIB_VERSION_CURRENT}.${LIB_VERSION_AGE}.${LIB_VERSION_REVISION}" )
|
||||
|
||||
# Options disabled by default
|
||||
option ( enable-coverage "enable gcov code coverage" off )
|
||||
option ( enable-debug "enable debugging (default=no)" off )
|
||||
option ( enable-floats "enable type float instead of double for DSP samples" off )
|
||||
option ( enable-fpe-check "enable Floating Point Exception checks and debug messages" off )
|
||||
option ( enable-portaudio "compile PortAudio support" off )
|
||||
option ( enable-profiling "profile the dsp code" off )
|
||||
option ( enable-trap-on-fpe "enable SIGFPE trap on Floating Point Exceptions" off )
|
||||
option ( enable-ubsan "compile and link against UBSan (for debugging fluidsynth internals)" off )
|
||||
if ( MSVC )
|
||||
option ( enable-static-mscrt "use static MS Visual C++ runtime" off )
|
||||
endif ( MSVC )
|
||||
|
||||
# Options enabled by default
|
||||
option ( enable-aufile "compile support for sound file output" on )
|
||||
|
@ -86,8 +91,8 @@ option ( enable-wasapi "compile Windows WASAPI support (if it is available)" on
|
|||
option ( enable-waveout "compile Windows WaveOut support (if it is available)" on )
|
||||
option ( enable-winmidi "compile Windows MIDI support (if it is available)" on )
|
||||
option ( enable-sdl2 "compile SDL2 audio support (if it is available)" on )
|
||||
option ( enable-pkgconfig "use pkg-config to locate fluidsynth's (mostly optional) dependencies" on )
|
||||
option ( enable-pulseaudio "compile PulseAudio support (if it is available)" on )
|
||||
option ( enable-pipewire "compile PipeWire support (if it is available)" on )
|
||||
option ( enable-readline "compile readline lib line editing (if it is available)" on )
|
||||
option ( enable-threads "enable multi-threading support (such as parallel voice synthesis)" on )
|
||||
option ( enable-openmp "enable OpenMP support (parallelization of soundfont decoding, vectorization of voice mixing, etc.)" on )
|
||||
|
@ -113,20 +118,6 @@ if ( CMAKE_SYSTEM MATCHES "OS2" )
|
|||
set ( enable-ipv6 off )
|
||||
endif ( CMAKE_SYSTEM MATCHES "OS2" )
|
||||
|
||||
# Initialize the library directory name suffix.
|
||||
if (NOT MINGW AND NOT MSVC AND NOT CMAKE_SYSTEM_NAME MATCHES "FreeBSD|DragonFly")
|
||||
if ( CMAKE_SIZEOF_VOID_P EQUAL 8 )
|
||||
set ( _init_lib_suffix "64" )
|
||||
else ( CMAKE_SIZEOF_VOID_P EQUAL 8 )
|
||||
set ( _init_lib_suffix "" )
|
||||
endif ( CMAKE_SIZEOF_VOID_P EQUAL 8 )
|
||||
else ()
|
||||
set ( _init_lib_suffix "" )
|
||||
endif()
|
||||
set ( LIB_SUFFIX ${_init_lib_suffix} CACHE STRING
|
||||
"library directory name suffix (32/64/nothing)" )
|
||||
mark_as_advanced ( LIB_SUFFIX )
|
||||
|
||||
# the default C standard to use for all targets
|
||||
set(CMAKE_C_STANDARD 90)
|
||||
|
||||
|
@ -134,6 +125,7 @@ set(CMAKE_C_STANDARD 90)
|
|||
set(CMAKE_CXX_STANDARD 98)
|
||||
|
||||
# whether to use gnu extensions
|
||||
set(CMAKE_C_EXTENSIONS ON)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
|
||||
# Compile with position independent code if the user requested a shared lib, i.e. no PIC if static requested.
|
||||
|
@ -150,11 +142,11 @@ if ( NOT OS2 )
|
|||
endif ( NOT OS2 )
|
||||
|
||||
# enforce visibility control for all types of cmake targets
|
||||
if ( POLICY CMP0063 )
|
||||
if ( POLICY CMP0063 ) # since version 3.3, CMake version 3.21.2 warns when the policy is not set and uses OLD behavior.
|
||||
cmake_policy ( SET CMP0063 NEW )
|
||||
endif ( POLICY CMP0063 )
|
||||
|
||||
# Default install directory names
|
||||
# Default install directory names, some provided by GNUInstallDirs
|
||||
include ( DefaultDirs )
|
||||
|
||||
# Basic C library checks
|
||||
|
@ -189,6 +181,7 @@ if ( NOT HAVE_LONG_LONG AND NOT MSVC)
|
|||
message ( FATAL_ERROR "Your compiler does not support intrinsic type 'long long'. Unable to compile fluidsynth." )
|
||||
endif ()
|
||||
|
||||
include ( CMakePrintHelpers ) # for cmake_print_properties() and cmake_print_variables()
|
||||
include ( TestInline )
|
||||
include ( TestVLA )
|
||||
include ( TestBigEndian )
|
||||
|
@ -329,6 +322,10 @@ if ( WIN32 )
|
|||
set ( CMAKE_DEBUG_POSTFIX "_debug" )
|
||||
endif ( NOT MSVC )
|
||||
|
||||
if ( enable-static-msvcrt )
|
||||
set ( CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>" )
|
||||
endif ( enable-static-msvcrt )
|
||||
|
||||
# MinGW compiler (a Windows GCC port)
|
||||
if ( MINGW )
|
||||
set ( MINGW32 1 )
|
||||
|
@ -374,7 +371,7 @@ unset ( MACOSX_FRAMEWORK CACHE )
|
|||
if ( CMAKE_SYSTEM MATCHES "Darwin" )
|
||||
set ( DARWIN 1 )
|
||||
set ( CMAKE_INSTALL_NAME_DIR
|
||||
${CMAKE_INSTALL_PREFIX}/${LIB_INSTALL_DIR} )
|
||||
${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR} )
|
||||
if ( enable-coreaudio )
|
||||
check_include_file ( CoreAudio/AudioHardware.h COREAUDIO_FOUND )
|
||||
if ( COREAUDIO_FOUND )
|
||||
|
@ -417,17 +414,15 @@ if ( enable-profiling )
|
|||
|
||||
set ( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OPT_FLAGS}" )
|
||||
|
||||
if ( CMAKE_VERSION VERSION_GREATER_EQUAL "3.6.0" )
|
||||
find_program( CLANG_TIDY
|
||||
NAMES "clang-tidy"
|
||||
DOC "Path to clang-tidy executable" )
|
||||
find_program( CLANG_TIDY
|
||||
NAMES "clang-tidy"
|
||||
DOC "Path to clang-tidy executable" )
|
||||
|
||||
if ( CLANG_TIDY )
|
||||
message ( STATUS "Found clang-tidy at ${CLANG_TIDY}" )
|
||||
execute_process ( COMMAND ${CLANG_TIDY} "--version" )
|
||||
set ( CMAKE_C_CLANG_TIDY ${CLANG_TIDY} )
|
||||
endif ( CLANG_TIDY )
|
||||
endif ( CMAKE_VERSION VERSION_GREATER_EQUAL "3.6.0" )
|
||||
if ( CLANG_TIDY )
|
||||
message ( STATUS "Found clang-tidy at ${CLANG_TIDY}" )
|
||||
execute_process ( COMMAND ${CLANG_TIDY} "--version" )
|
||||
set ( CMAKE_C_CLANG_TIDY ${CLANG_TIDY} )
|
||||
endif ( CLANG_TIDY )
|
||||
|
||||
endif ( enable-profiling )
|
||||
|
||||
|
@ -445,11 +440,6 @@ if ( enable-fpe-check AND NOT APPLE AND NOT WIN32 )
|
|||
set ( FPE_CHECK 1 )
|
||||
endif ( enable-fpe-check AND NOT APPLE AND NOT WIN32 )
|
||||
|
||||
if ( enable-debug )
|
||||
set ( CMAKE_BUILD_TYPE "Debug" CACHE STRING
|
||||
"Choose the build type, options: Debug Release RelWithDebInfo MinSizeRel" FORCE )
|
||||
endif ( enable-debug )
|
||||
|
||||
if ( NOT CMAKE_BUILD_TYPE )
|
||||
set ( CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING
|
||||
"Choose the build type, options: Debug Release RelWithDebInfo MinSizeRel" FORCE )
|
||||
|
@ -466,13 +456,13 @@ endif ( CMAKE_BUILD_TYPE MATCHES "Debug" )
|
|||
file(GLOB_RECURSE
|
||||
ALL_SOURCE_FILES
|
||||
LIST_DIRECTORIES false
|
||||
${CMAKE_SOURCE_DIR}/*.[chi]
|
||||
${CMAKE_SOURCE_DIR}/*.[chi]pp
|
||||
${CMAKE_SOURCE_DIR}/*.[chi]xx
|
||||
${CMAKE_SOURCE_DIR}/*.cc
|
||||
${CMAKE_SOURCE_DIR}/*.hh
|
||||
${CMAKE_SOURCE_DIR}/*.ii
|
||||
${CMAKE_SOURCE_DIR}/*.[CHI]
|
||||
${FluidSynth_SOURCE_DIR}/*.[chi]
|
||||
${FluidSynth_SOURCE_DIR}/*.[chi]pp
|
||||
${FluidSynth_SOURCE_DIR}/*.[chi]xx
|
||||
${FluidSynth_SOURCE_DIR}/*.cc
|
||||
${FluidSynth_SOURCE_DIR}/*.hh
|
||||
${FluidSynth_SOURCE_DIR}/*.ii
|
||||
${FluidSynth_SOURCE_DIR}/*.[CHI]
|
||||
)
|
||||
|
||||
find_program ( ASTYLE "astyle" )
|
||||
|
@ -492,202 +482,236 @@ if ( ASTYLE )
|
|||
)
|
||||
endif(ASTYLE)
|
||||
|
||||
if(NOT enable-pkgconfig)
|
||||
if ( NOT WIN32 )
|
||||
find_package ( PkgConfig REQUIRED )
|
||||
|
||||
FIND_LIBRARY( GLIB_LIB NAMES glib glib-2.0 PATH GLIB_LIBRARY_DIR )
|
||||
FIND_LIBRARY( GTHREAD_LIB NAMES gthread gthread-2.0 PATH GTHREAD_LIBRARY_DIR )
|
||||
FIND_PATH( GLIBH_DIR glib.h PATH GLIB_INCLUDE_DIR )
|
||||
FIND_PATH( GLIBCONF_DIR glibconfig.h PATH GLIBCONF_INCLUDE_DIR )
|
||||
# Mandatory libraries: glib and gthread
|
||||
pkg_check_modules ( GLIB REQUIRED glib-2.0>=2.6.5 gthread-2.0>=2.6.5 IMPORTED_TARGET )
|
||||
list( APPEND PC_REQUIRES_PRIV "glib-2.0" "gthread-2.0")
|
||||
|
||||
IF( GLIB_LIB MATCHES "GLIB_LIB-NOTFOUND" OR
|
||||
GTHREAD_LIB MATCHES "GTHREAD_LIB-NOTFOUND" OR
|
||||
GLIBH_DIR MATCHES "GLIBH_DIR-NOTFOUND" OR
|
||||
GLIBCONF_DIR MATCHES "GLIBCONF_DIR-NOTFOUND")
|
||||
message( WARNING "Not sure if I found GLIB, continuing anyway.")
|
||||
ENDIF()
|
||||
if ( GLIB_glib-2.0_VERSION AND GLIB_glib-2.0_VERSION VERSION_LESS "2.26.0" )
|
||||
message ( WARNING "Your version of glib is very old. This may cause problems with fluidsynth's sample cache on Windows. Consider updating to glib 2.26 or newer!" )
|
||||
endif ( GLIB_glib-2.0_VERSION AND GLIB_glib-2.0_VERSION VERSION_LESS "2.26.0" )
|
||||
set ( WIN32_GLIBSTUBS OFF )
|
||||
set ( WITH_GLIB_STUBS 0 )
|
||||
else ( NOT WIN32 )
|
||||
set ( WIN32_GLIBSTUBS ON )
|
||||
set ( WITH_GLIB_STUBS 1 )
|
||||
endif ( NOT WIN32 )
|
||||
|
||||
SET( GLIB_INCLUDE_DIRS ${GLIBH_DIR} ${GLIBCONF_DIR} )
|
||||
SET( GLIB_LIBRARIES ${GLIB_LIB} ${GTHREAD_LIB} )
|
||||
include ( PkgConfigHelpers ) # has unset_pkg_config()
|
||||
|
||||
message( STATUS "GLIB_INCLUDE_DIRS: " ${GLIB_INCLUDE_DIRS} )
|
||||
message( STATUS "GLIB_LIBRARIES: " ${GLIB_LIBRARIES} )
|
||||
if ( NOT PkgConfig_FOUND )
|
||||
set ( enable-pulseaudio OFF )
|
||||
set ( enable-alsa OFF )
|
||||
set ( enable-portaudio OFF )
|
||||
set ( enable-jack OFF )
|
||||
set ( enable-pipewire OFF )
|
||||
set ( enable-lash OFF )
|
||||
set ( enable-systemd OFF )
|
||||
set ( enable-dbus OFF )
|
||||
set ( enable-ladspa OFF )
|
||||
set ( enable-libinstpatch OFF )
|
||||
set ( enable-sdl2 OFF )
|
||||
set ( enable-oboe OFF )
|
||||
set ( enable-readline OFF )
|
||||
endif ( NOT PkgConfig_FOUND )
|
||||
|
||||
else(NOT enable-pkgconfig)
|
||||
|
||||
find_package ( PkgConfig REQUIRED )
|
||||
|
||||
# Mandatory libraries: glib and gthread
|
||||
pkg_check_modules ( GLIB REQUIRED glib-2.0>=2.6.5 gthread-2.0>=2.6.5 )
|
||||
list( APPEND PC_REQUIRES_PRIV "glib-2.0" "gthread-2.0")
|
||||
|
||||
if ( GLIB_glib-2.0_VERSION AND GLIB_glib-2.0_VERSION VERSION_LESS "2.26.0" )
|
||||
message ( WARNING "Your version of glib is very old. This may cause problems with fluidsynth's sample cache on Windows. Consider updating to glib 2.26 or newer!" )
|
||||
endif ( GLIB_glib-2.0_VERSION AND GLIB_glib-2.0_VERSION VERSION_LESS "2.26.0" )
|
||||
|
||||
include ( UnsetPkgConfig )
|
||||
|
||||
# Optional features
|
||||
unset ( LIBSNDFILE_SUPPORT CACHE )
|
||||
unset ( LIBSNDFILE_HASVORBIS CACHE )
|
||||
if ( enable-libsndfile )
|
||||
pkg_check_modules ( LIBSNDFILE sndfile>=1.0.0 )
|
||||
set ( LIBSNDFILE_SUPPORT ${LIBSNDFILE_FOUND} )
|
||||
if ( LIBSNDFILE_SUPPORT )
|
||||
list( APPEND PC_REQUIRES_PRIV "sndfile")
|
||||
message (DEBUG "LIBSNDFILE_STATIC_LIBRARIES: ${LIBSNDFILE_STATIC_LIBRARIES}")
|
||||
message (DEBUG "LIBSNDFILE_STATIC_LINK_LIBRARIES: ${LIBSNDFILE_STATIC_LINK_LIBRARIES}")
|
||||
message (DEBUG "LIBSNDFILE_STATIC_LDFLAGS: ${LIBSNDFILE_STATIC_LDFLAGS}")
|
||||
message (DEBUG "LIBSNDFILE_STATIC_LDFLAGS_OTHER: ${LIBSNDFILE_STATIC_LDFLAGS_OTHER}")
|
||||
if ( LIBSNDFILE_STATIC_LIBRARIES MATCHES "vorbis" OR
|
||||
LIBSNDFILE_STATIC_LDFLAGS MATCHES "vorbis" OR
|
||||
LIBSNDFILE_STATIC_LDFLAGS_OTHER MATCHES "vorbis" )
|
||||
set ( LIBSNDFILE_HASVORBIS 1 )
|
||||
else ()
|
||||
message ( NOTICE "Seems like libsndfile was compiled without OGG/Vorbis support." )
|
||||
endif ()
|
||||
endif ( LIBSNDFILE_SUPPORT )
|
||||
else ( enable-libsndfile )
|
||||
# Optional features
|
||||
unset ( LIBSNDFILE_SUPPORT CACHE )
|
||||
unset ( LIBSNDFILE_HASVORBIS CACHE )
|
||||
if ( enable-libsndfile )
|
||||
if ( PkgConfig_FOUND )
|
||||
pkg_check_modules ( LIBSNDFILE sndfile>=1.0.0 IMPORTED_TARGET )
|
||||
set ( LIBSNDFILE_SUPPORT ${LIBSNDFILE_FOUND} )
|
||||
else ( PkgConfig_FOUND )
|
||||
find_package(SndFile CONFIG)
|
||||
set ( LIBSNDFILE_SUPPORT ${SNDFILE_FOUND} )
|
||||
endif ( PkgConfig_FOUND)
|
||||
if ( LIBSNDFILE_SUPPORT )
|
||||
#[[ cmake_print_variables (
|
||||
LIBSNDFILE_STATIC_LIBRARIES
|
||||
LIBSNDFILE_STATIC_LINK_LIBRARIES
|
||||
LIBSNDFILE_STATIC_LDFLAGS
|
||||
LIBSNDFILE_STATIC_LDFLAGS_OTHER ) ]]
|
||||
list( APPEND PC_REQUIRES_PRIV "sndfile")
|
||||
if ( LIBSNDFILE_STATIC_LIBRARIES MATCHES "vorbis" OR
|
||||
SndFile_WITH_EXTERNAL_LIBS OR
|
||||
LIBSNDFILE_STATIC_LDFLAGS MATCHES "vorbis" OR
|
||||
LIBSNDFILE_STATIC_LDFLAGS_OTHER MATCHES "vorbis" )
|
||||
set ( LIBSNDFILE_HASVORBIS 1 )
|
||||
else ()
|
||||
message ( NOTICE "Seems like libsndfile was compiled without OGG/Vorbis support." )
|
||||
endif ()
|
||||
#[[ cmake_print_properties( TARGETS PkgConfig::LIBSNDFILE
|
||||
PROPERTIES
|
||||
INTERFACE_COMPILE_OPTIONS
|
||||
INTERFACE_INCLUDE_DIRECTORIES
|
||||
INTERFACE_LINK_OPTIONS
|
||||
INTERFACE_LINK_LIBRARIES ) ]]
|
||||
sanitize_target_dirs(PkgConfig::LIBSNDFILE)
|
||||
endif ( LIBSNDFILE_SUPPORT )
|
||||
else ( enable-libsndfile )
|
||||
unset_pkg_config ( LIBSNDFILE )
|
||||
unset_pkg_config ( LIBSNDFILE_VORBIS )
|
||||
endif ( enable-libsndfile )
|
||||
endif ( enable-libsndfile )
|
||||
|
||||
unset ( PULSE_SUPPORT CACHE )
|
||||
if ( enable-pulseaudio )
|
||||
pkg_check_modules ( PULSE libpulse-simple>=0.9.8 )
|
||||
unset ( PULSE_SUPPORT CACHE )
|
||||
if ( enable-pulseaudio )
|
||||
pkg_check_modules ( PULSE libpulse-simple>=0.9.8 IMPORTED_TARGET )
|
||||
set ( PULSE_SUPPORT ${PULSE_FOUND} )
|
||||
if ( PULSE_SUPPORT )
|
||||
list( APPEND PC_REQUIRES_PRIV "libpulse-simple")
|
||||
list( APPEND PC_REQUIRES_PRIV "libpulse-simple")
|
||||
endif ( PULSE_SUPPORT )
|
||||
else ( enable-pulseaudio )
|
||||
else ( enable-pulseaudio )
|
||||
unset_pkg_config ( PULSE )
|
||||
endif ( enable-pulseaudio )
|
||||
endif ( enable-pulseaudio )
|
||||
|
||||
unset ( ALSA_SUPPORT CACHE )
|
||||
if ( enable-alsa )
|
||||
pkg_check_modules ( ALSA alsa>=0.9.1 )
|
||||
unset ( ALSA_SUPPORT CACHE )
|
||||
if ( enable-alsa )
|
||||
pkg_check_modules ( ALSA alsa>=0.9.1 IMPORTED_TARGET )
|
||||
set ( ALSA_SUPPORT ${ALSA_FOUND} )
|
||||
if ( ALSA_SUPPORT )
|
||||
list( APPEND PC_REQUIRES_PRIV "alsa")
|
||||
list( APPEND PC_REQUIRES_PRIV "alsa")
|
||||
endif ( ALSA_SUPPORT )
|
||||
else ( enable-alsa )
|
||||
else ( enable-alsa )
|
||||
unset_pkg_config ( ALSA )
|
||||
endif ( enable-alsa )
|
||||
endif ( enable-alsa )
|
||||
|
||||
unset ( PORTAUDIO_SUPPORT CACHE )
|
||||
if ( enable-portaudio )
|
||||
pkg_check_modules ( PORTAUDIO portaudio-2.0>=19 )
|
||||
unset ( PORTAUDIO_SUPPORT CACHE )
|
||||
if ( enable-portaudio )
|
||||
pkg_check_modules ( PORTAUDIO portaudio-2.0>=19 IMPORTED_TARGET )
|
||||
set ( PORTAUDIO_SUPPORT ${PORTAUDIO_FOUND} )
|
||||
if ( PORTAUDIO_SUPPORT )
|
||||
list( APPEND PC_REQUIRES_PRIV "portaudio-2.0")
|
||||
list( APPEND PC_REQUIRES_PRIV "portaudio-2.0")
|
||||
endif ()
|
||||
else ( enable-portaudio )
|
||||
else ( enable-portaudio )
|
||||
unset_pkg_config ( PORTAUDIO )
|
||||
endif ( enable-portaudio )
|
||||
endif ( enable-portaudio )
|
||||
|
||||
unset ( JACK_SUPPORT CACHE )
|
||||
if ( enable-jack )
|
||||
pkg_check_modules ( JACK jack )
|
||||
unset ( JACK_SUPPORT CACHE )
|
||||
if ( enable-jack )
|
||||
pkg_check_modules ( JACK jack IMPORTED_TARGET )
|
||||
set ( JACK_SUPPORT ${JACK_FOUND} )
|
||||
if ( JACK_SUPPORT )
|
||||
list( APPEND PC_REQUIRES_PRIV "jack")
|
||||
endif ()
|
||||
else ( enable-jack )
|
||||
if (JACK_SUPPORT)
|
||||
sanitize_target_dirs(PkgConfig::JACK)
|
||||
list( APPEND PC_REQUIRES_PRIV "jack")
|
||||
endif()
|
||||
else ( enable-jack )
|
||||
unset_pkg_config ( JACK )
|
||||
endif ( enable-jack )
|
||||
endif ( enable-jack )
|
||||
|
||||
unset ( LASH_SUPPORT CACHE )
|
||||
if ( enable-lash )
|
||||
pkg_check_modules ( LASH lash-1.0>=0.3 )
|
||||
unset ( PIPEWIRE_SUPPORT CACHE )
|
||||
if ( enable-pipewire )
|
||||
pkg_check_modules ( PIPEWIRE libpipewire-0.3 IMPORTED_TARGET )
|
||||
set ( PIPEWIRE_SUPPORT ${PIPEWIRE_FOUND} )
|
||||
if ( PIPEWIRE_SUPPORT )
|
||||
list( APPEND PC_REQUIRES_PRIV "libpipewire-0.3")
|
||||
endif()
|
||||
else ( enable-pipewire )
|
||||
unset_pkg_config ( PIPEWIRE )
|
||||
endif ( enable-pipewire )
|
||||
|
||||
unset ( LASH_SUPPORT CACHE )
|
||||
if ( enable-lash )
|
||||
pkg_check_modules ( LASH lash-1.0>=0.3 IMPORTED_TARGET )
|
||||
if ( LASH_FOUND )
|
||||
set ( LASH_SUPPORT 1 )
|
||||
add_definitions ( -DHAVE_LASH )
|
||||
sanitize_target_dirs(PkgConfig::LASH)
|
||||
list( APPEND PC_REQUIRES_PRIV "lash-1.0")
|
||||
endif ( LASH_FOUND )
|
||||
else ( enable-lash )
|
||||
else ( enable-lash )
|
||||
unset_pkg_config ( LASH )
|
||||
remove_definitions( -DHAVE_LASH )
|
||||
endif ( enable-lash )
|
||||
endif ( enable-lash )
|
||||
|
||||
unset ( SYSTEMD_SUPPORT CACHE )
|
||||
if ( enable-systemd )
|
||||
pkg_check_modules ( SYSTEMD libsystemd )
|
||||
set ( SYSTEMD_SUPPORT ${SYSTEMD_FOUND} )
|
||||
if ( SYSTEMD_SUPPORT )
|
||||
list( APPEND PC_REQUIRES_PRIV "libsystemd")
|
||||
endif ( SYSTEMD_SUPPORT )
|
||||
else ( enable-systemd )
|
||||
unset_pkg_config ( SYSTEMD )
|
||||
endif ( enable-systemd )
|
||||
unset ( SYSTEMD_SUPPORT CACHE )
|
||||
if ( enable-systemd )
|
||||
pkg_check_modules ( SYSTEMD libsystemd IMPORTED_TARGET )
|
||||
set ( SYSTEMD_SUPPORT ${SYSTEMD_FOUND} )
|
||||
if ( SYSTEMD_SUPPORT )
|
||||
list( APPEND PC_REQUIRES_PRIV "libsystemd")
|
||||
endif ( SYSTEMD_SUPPORT )
|
||||
else ( enable-systemd )
|
||||
unset_pkg_config ( SYSTEMD )
|
||||
endif ( enable-systemd )
|
||||
|
||||
unset ( DBUS_SUPPORT CACHE )
|
||||
if ( enable-dbus )
|
||||
pkg_check_modules ( DBUS dbus-1>=1.0.0 )
|
||||
set ( DBUS_SUPPORT ${DBUS_FOUND} )
|
||||
if ( DBUS_SUPPORT )
|
||||
list( APPEND PC_REQUIRES_PRIV "dbus-1")
|
||||
endif ()
|
||||
else ( enable-dbus )
|
||||
unset ( DBUS_SUPPORT CACHE )
|
||||
if ( enable-dbus )
|
||||
pkg_check_modules ( DBUS dbus-1>=1.0.0 IMPORTED_TARGET )
|
||||
set ( DBUS_SUPPORT ${DBUS_FOUND} )
|
||||
if ( DBUS_SUPPORT )
|
||||
list( APPEND PC_REQUIRES_PRIV "dbus-1")
|
||||
endif ()
|
||||
else ( enable-dbus )
|
||||
unset_pkg_config ( DBUS )
|
||||
endif ( enable-dbus )
|
||||
endif ( enable-dbus )
|
||||
|
||||
unset ( LADSPA_SUPPORT CACHE )
|
||||
if ( enable-ladspa )
|
||||
check_include_file ( ladspa.h LADSPA_SUPPORT )
|
||||
if ( LADSPA_SUPPORT )
|
||||
pkg_check_modules ( GMODULE REQUIRED gmodule-2.0>=2.6.5 )
|
||||
set ( LADSPA 1 )
|
||||
list( APPEND PC_REQUIRES_PRIV "gmodule-2.0")
|
||||
endif ( LADSPA_SUPPORT )
|
||||
endif ( enable-ladspa )
|
||||
unset ( LADSPA_SUPPORT CACHE )
|
||||
if ( enable-ladspa )
|
||||
check_include_file ( ladspa.h LADSPA_SUPPORT )
|
||||
if ( LADSPA_SUPPORT )
|
||||
pkg_check_modules ( GMODULE REQUIRED gmodule-2.0>=2.6.5 IMPORTED_TARGET )
|
||||
set ( LADSPA 1 )
|
||||
list( APPEND PC_REQUIRES_PRIV "gmodule-2.0")
|
||||
endif ( LADSPA_SUPPORT )
|
||||
endif ( enable-ladspa )
|
||||
|
||||
unset ( LIBINSTPATCH_SUPPORT CACHE )
|
||||
if ( enable-libinstpatch )
|
||||
pkg_check_modules ( LIBINSTPATCH libinstpatch-1.0>=1.1.0 )
|
||||
set ( LIBINSTPATCH_SUPPORT ${LIBINSTPATCH_FOUND} )
|
||||
if ( LIBINSTPATCH_SUPPORT )
|
||||
list( APPEND PC_REQUIRES_PRIV "libinstpatch-1.0")
|
||||
endif (LIBINSTPATCH_SUPPORT )
|
||||
endif ( enable-libinstpatch )
|
||||
unset ( LIBINSTPATCH_SUPPORT CACHE )
|
||||
if ( enable-libinstpatch )
|
||||
pkg_check_modules ( LIBINSTPATCH libinstpatch-1.0>=1.1.0 IMPORTED_TARGET )
|
||||
set ( LIBINSTPATCH_SUPPORT ${LIBINSTPATCH_FOUND} )
|
||||
if ( LIBINSTPATCH_SUPPORT )
|
||||
list( APPEND PC_REQUIRES_PRIV "libinstpatch-1.0")
|
||||
#[[ cmake_print_properties( TARGETS PkgConfig::LIBINSTPATCH
|
||||
PROPERTIES
|
||||
INTERFACE_COMPILE_OPTIONS
|
||||
INTERFACE_INCLUDE_DIRECTORIES
|
||||
INTERFACE_LINK_DIRECTORIES
|
||||
INTERFACE_LINK_OPTIONS
|
||||
INTERFACE_LINK_LIBRARIES ) ]]
|
||||
sanitize_target_dirs(PkgConfig::LIBINSTPATCH)
|
||||
endif (LIBINSTPATCH_SUPPORT )
|
||||
endif ( enable-libinstpatch )
|
||||
|
||||
unset ( SDL2_SUPPORT CACHE )
|
||||
if ( enable-sdl2 )
|
||||
pkg_check_modules ( SDL2 sdl2 )
|
||||
set ( SDL2_SUPPORT ${SDL2_FOUND} )
|
||||
if ( SDL2_SUPPORT )
|
||||
list( APPEND PC_REQUIRES_PRIV "sdl2")
|
||||
endif ( SDL2_SUPPORT )
|
||||
else ( enable-sdl2 )
|
||||
unset_pkg_config ( SDL2 )
|
||||
endif ( enable-sdl2 )
|
||||
unset ( SDL2_SUPPORT CACHE )
|
||||
if ( enable-sdl2 )
|
||||
pkg_check_modules ( SDL2 sdl2>=2.0.4 IMPORTED_TARGET )
|
||||
set ( SDL2_SUPPORT ${SDL2_FOUND} )
|
||||
if ( SDL2_SUPPORT )
|
||||
list( APPEND PC_REQUIRES_PRIV "sdl2")
|
||||
endif ( SDL2_SUPPORT )
|
||||
else ( enable-sdl2 )
|
||||
unset_pkg_config ( SDL2 )
|
||||
endif ( enable-sdl2 )
|
||||
|
||||
unset ( OBOE_SUPPORT CACHE )
|
||||
if ( enable-oboe )
|
||||
pkg_check_modules ( OBOE oboe-1.0 )
|
||||
if ( OBOE_FOUND )
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set ( OBOE_SUPPORT 1 )
|
||||
list( APPEND PC_REQUIRES_PRIV "oboe-1.0")
|
||||
endif ( OBOE_FOUND )
|
||||
endif ( enable-oboe )
|
||||
unset ( OBOE_SUPPORT CACHE )
|
||||
if ( enable-oboe )
|
||||
pkg_check_modules ( OBOE oboe-1.0 IMPORTED_TARGET )
|
||||
if ( OBOE_FOUND )
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set ( OBOE_SUPPORT 1 )
|
||||
list( APPEND PC_REQUIRES_PRIV "oboe-1.0")
|
||||
endif ( OBOE_FOUND )
|
||||
endif ( enable-oboe )
|
||||
|
||||
unset ( WITH_READLINE CACHE )
|
||||
unset ( READLINE_LIBS CACHE )
|
||||
if ( enable-readline )
|
||||
pkg_check_modules ( READLINE readline )
|
||||
if ( READLINE_FOUND )
|
||||
list( APPEND PC_REQUIRES_PRIV "readline")
|
||||
else ( READLINE_FOUND )
|
||||
find_package ( READLINE )
|
||||
set ( READLINE_FOUND ${HAVE_READLINE} )
|
||||
endif ( READLINE_FOUND )
|
||||
if ( READLINE_FOUND )
|
||||
set ( WITH_READLINE 1 )
|
||||
set ( READLINE_LIBS ${READLINE_LIBRARIES} )
|
||||
endif ( READLINE_FOUND )
|
||||
endif ( enable-readline )
|
||||
|
||||
endif(NOT enable-pkgconfig)
|
||||
unset ( WITH_READLINE CACHE )
|
||||
unset ( READLINE_LIBS CACHE )
|
||||
if ( enable-readline )
|
||||
pkg_check_modules ( READLINE readline QUIET IMPORTED_TARGET )
|
||||
if ( READLINE_FOUND )
|
||||
list( APPEND PC_REQUIRES_PRIV "readline")
|
||||
else ( READLINE_FOUND )
|
||||
find_package ( READLINE )
|
||||
set ( READLINE_FOUND ${HAVE_READLINE} )
|
||||
endif ( READLINE_FOUND )
|
||||
if ( READLINE_FOUND )
|
||||
set ( WITH_READLINE 1 )
|
||||
set ( READLINE_LIBS ${READLINE_LIBRARIES} )
|
||||
endif ( READLINE_FOUND )
|
||||
endif ( enable-readline )
|
||||
|
||||
unset ( AUFILE_SUPPORT CACHE )
|
||||
if ( enable-aufile )
|
||||
|
@ -733,26 +757,26 @@ endif ( enable-threads )
|
|||
unset ( HAVE_OPENMP CACHE )
|
||||
find_package ( OpenMP QUIET )
|
||||
if (enable-openmp AND ( OpenMP_FOUND OR OpenMP_C_FOUND ) )
|
||||
message(STATUS "Found OpenMP ${OpenMP_C_SPEC_DATE}")
|
||||
# require at least OMP 4.0
|
||||
if ( ( NOT OpenMP_C_SPEC_DATE LESS "201307" ) OR NOT ( OpenMP_C_VERSION VERSION_LESS "4.0" ) )
|
||||
set ( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}" )
|
||||
set ( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}" )
|
||||
|
||||
# include dir and library link seems to be required for Xcode 12.5 (issue #917)
|
||||
include_directories ( SYSTEM ${OpenMP_C_INCLUDE_DIRS} )
|
||||
set ( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}" )
|
||||
set ( LIBFLUID_LIBS "${OpenMP_C_LIBRARIES};${LIBFLUID_LIBS}" )
|
||||
set ( HAVE_OPENMP 1 )
|
||||
message(STATUS "Found OpenMP version: ${OpenMP_C_VERSION} date: ${OpenMP_C_SPEC_DATE}")
|
||||
if ( TARGET OpenMP::OpenMP_C AND (( NOT OpenMP_C_SPEC_DATE LESS "201307" ) OR NOT ( OpenMP_C_VERSION VERSION_LESS "4.0" )) )
|
||||
#[[ cmake_print_properties( TARGETS OpenMP::OpenMP_C
|
||||
PROPERTIES
|
||||
INTERFACE_COMPILE_OPTIONS
|
||||
INTERFACE_INCLUDE_DIRECTORIES
|
||||
INTERFACE_LINK_OPTIONS
|
||||
INTERFACE_LINK_LIBRARIES ) ]]
|
||||
set ( HAVE_OPENMP 1 )
|
||||
else()
|
||||
message(STATUS " OpenMP version is not supported. Feature disabled.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# manipulate some variables to setup a proper test env
|
||||
set(TEST_SOUNDFONT "${CMAKE_SOURCE_DIR}/sf2/VintageDreamsWaves-v2.sf2")
|
||||
set(TEST_SOUNDFONT_UTF8_1 "${CMAKE_SOURCE_DIR}/sf2/\\xE2\\x96\\xA0VintageDreamsWaves-v2\\xE2\\x96\\xA0.sf2")
|
||||
set(TEST_SOUNDFONT_UTF8_2 "${CMAKE_SOURCE_DIR}/sf2/VìntàgèDrèàmsWàvès-v2.sf2")
|
||||
set(TEST_SOUNDFONT_SF3 "${CMAKE_SOURCE_DIR}/sf2/VintageDreamsWaves-v2.sf3")
|
||||
set(TEST_MIDI_UTF8 "${CMAKE_SOURCE_DIR}/test/èmpty.mid")
|
||||
set(TEST_SOUNDFONT "${FluidSynth_SOURCE_DIR}/sf2/VintageDreamsWaves-v2.sf2")
|
||||
set(TEST_SOUNDFONT_UTF8_1 "${FluidSynth_SOURCE_DIR}/sf2/\\xE2\\x96\\xA0VintageDreamsWaves-v2\\xE2\\x96\\xA0.sf2")
|
||||
set(TEST_SOUNDFONT_UTF8_2 "${FluidSynth_SOURCE_DIR}/sf2/VìntàgèDrèàmsWàvès-v2.sf2")
|
||||
set(TEST_SOUNDFONT_SF3 "${FluidSynth_SOURCE_DIR}/sf2/VintageDreamsWaves-v2.sf3")
|
||||
set(TEST_MIDI_UTF8 "${FluidSynth_SOURCE_DIR}/test/èmpty.mid")
|
||||
|
||||
# Make sure to link against libm before checking for math functions below
|
||||
set ( CMAKE_REQUIRED_LIBRARIES "${LIBFLUID_LIBS};${WINDOWS_LIBS}" )
|
||||
|
@ -822,23 +846,8 @@ if ( HAVE_SOCKLEN_T )
|
|||
endif ( HAVE_SOCKLEN_T )
|
||||
|
||||
# General configuration file
|
||||
configure_file ( ${CMAKE_SOURCE_DIR}/src/config.cmake
|
||||
${CMAKE_BINARY_DIR}/config.h )
|
||||
|
||||
# Setup linker directories NOW, as the command will apply only to targets created after it has been called.
|
||||
link_directories (
|
||||
${GLIB_LIBRARY_DIRS}
|
||||
${LASH_LIBRARY_DIRS}
|
||||
${JACK_LIBRARY_DIRS}
|
||||
${ALSA_LIBRARY_DIRS}
|
||||
${PULSE_LIBRARY_DIRS}
|
||||
${PORTAUDIO_LIBRARY_DIRS}
|
||||
${LIBSNDFILE_LIBRARY_DIRS}
|
||||
${DBUS_LIBRARY_DIRS}
|
||||
${SDL2_LIBRARY_DIRS}
|
||||
${OBOE_LIBRARY_DIRS}
|
||||
${LIBINSTPATCH_LIBRARY_DIRS}
|
||||
)
|
||||
configure_file ( ${FluidSynth_SOURCE_DIR}/src/config.cmake
|
||||
${FluidSynth_BINARY_DIR}/config.h )
|
||||
|
||||
# required to allow ctest to be called from top-level build directory
|
||||
ENABLE_TESTING()
|
||||
|
@ -851,83 +860,66 @@ add_subdirectory ( doc )
|
|||
# pkg-config support
|
||||
set ( prefix "${CMAKE_INSTALL_PREFIX}" )
|
||||
set ( exec_prefix "\${prefix}" )
|
||||
if ( IS_ABSOLUTE "${LIB_INSTALL_DIR}" )
|
||||
set ( libdir "${LIB_INSTALL_DIR}" )
|
||||
if ( IS_ABSOLUTE "${CMAKE_INSTALL_LIBDIR}" )
|
||||
set ( libdir "${CMAKE_INSTALL_LIBDIR}" )
|
||||
else ()
|
||||
set ( libdir "\${exec_prefix}/${LIB_INSTALL_DIR}" )
|
||||
set ( libdir "\${exec_prefix}/${CMAKE_INSTALL_LIBDIR}" )
|
||||
endif ()
|
||||
if ( IS_ABSOLUTE "${INCLUDE_INSTALL_DIR}" )
|
||||
set ( includedir "${INCLUDE_INSTALL_DIR}" )
|
||||
if ( IS_ABSOLUTE "${CMAKE_INSTALL_INCLUDEDIR}" )
|
||||
set ( includedir "${CMAKE_INSTALL_INCLUDEDIR}" )
|
||||
else ()
|
||||
set ( includedir "\${prefix}/${INCLUDE_INSTALL_DIR}" )
|
||||
set ( includedir "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}" )
|
||||
endif ()
|
||||
|
||||
if ( CMAKE_VERSION VERSION_EQUAL "3.12.0" OR CMAKE_VERSION VERSION_GREATER "3.12.0" )
|
||||
# retrieve all the private libs we depend on
|
||||
get_target_property ( LIBS_PRIVATE libfluidsynth INTERFACE_LINK_LIBRARIES)
|
||||
# make a copy
|
||||
set ( LIBS_PRIVATE_WITH_PATH ${LIBS_PRIVATE} )
|
||||
if ( PkgConfig_FOUND )
|
||||
generate_pkgconfig_spec(fluidsynth.pc.in ${FluidSynth_BINARY_DIR}/fluidsynth.pc libfluidsynth-OBJ)
|
||||
install ( FILES ${FluidSynth_BINARY_DIR}/fluidsynth.pc
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig )
|
||||
endif(PkgConfig_FOUND)
|
||||
|
||||
# this matches any path and any flag entries (starting with '-')
|
||||
set ( LIB_LIST_REGEX "(^(.+)\/([^\/]+)$)|(^\-.*$)" )
|
||||
# remove all entries from the list which are specified by path and which already have -l
|
||||
list ( FILTER LIBS_PRIVATE EXCLUDE REGEX ${LIB_LIST_REGEX} )
|
||||
# include only entries specifed by path
|
||||
list ( FILTER LIBS_PRIVATE_WITH_PATH INCLUDE REGEX ${LIB_LIST_REGEX} )
|
||||
# Exported targets for cmake: find_package(FluidSynth)
|
||||
# when installed, use CMAKE_PREFIX_PATH=fluidsynth-prefix;...
|
||||
# to use the build directory directly set the FluidSynth_DIR variable instead.
|
||||
|
||||
# prepend the linker flag to all entries except the ones that already have it
|
||||
list ( TRANSFORM LIBS_PRIVATE PREPEND "-l")
|
||||
list ( JOIN LIBS_PRIVATE " " LIBS_PRIVATE_JOINED )
|
||||
list ( JOIN LIBS_PRIVATE_WITH_PATH " " LIBS_PRIVATE_WITH_PATH_JOINED )
|
||||
else ()
|
||||
set ( LIBS_PRIVATE "" )
|
||||
set ( LIBS_PRIVATE_WITH_PATH "" )
|
||||
message ( DEPRECATION "Your version of CMake is old. A complete pkg-config file can not created. Get cmake 3.13.3 or newer." )
|
||||
endif ( CMAKE_VERSION VERSION_EQUAL "3.12.0" OR CMAKE_VERSION VERSION_GREATER "3.12.0" )
|
||||
# targets in the build directory
|
||||
export(EXPORT FluidSynthTargets
|
||||
FILE "${FluidSynth_BINARY_DIR}/FluidSynthTargets.cmake"
|
||||
NAMESPACE FluidSynth::
|
||||
)
|
||||
|
||||
list ( JOIN PC_REQUIRES_PRIV " " PC_REQUIRES_PRIV_JOINED )
|
||||
include(CMakePackageConfigHelpers) # SameMinorVersion requires CMake 3.11
|
||||
write_basic_package_version_file(
|
||||
FluidSynthConfigVersion.cmake
|
||||
VERSION ${VERSION}
|
||||
COMPATIBILITY SameMinorVersion
|
||||
)
|
||||
|
||||
configure_file ( fluidsynth.pc.in
|
||||
${CMAKE_BINARY_DIR}/fluidsynth.pc IMMEDIATE @ONLY )
|
||||
install ( FILES ${CMAKE_BINARY_DIR}/fluidsynth.pc
|
||||
DESTINATION ${LIB_INSTALL_DIR}/pkgconfig )
|
||||
# Here, configure_file() is used instead of the more orthodox macro
|
||||
# configure_package_config_file() because the latter does not
|
||||
# support generating a config.cmake file for both the installed
|
||||
# package and for using the build directory directly.
|
||||
configure_file(FluidSynthConfig.cmake.in FluidSynthConfig.cmake @ONLY)
|
||||
install(FILES "${FluidSynth_BINARY_DIR}/FluidSynthConfig.cmake"
|
||||
"${FluidSynth_BINARY_DIR}/FluidSynthConfigVersion.cmake"
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/fluidsynth
|
||||
)
|
||||
|
||||
# Extra targets for Unix build environments
|
||||
if ( UNIX )
|
||||
if ( DEFINED FLUID_DAEMON_ENV_FILE)
|
||||
configure_file ( fluidsynth.service.in
|
||||
${CMAKE_BINARY_DIR}/fluidsynth.service @ONLY )
|
||||
${FluidSynth_BINARY_DIR}/fluidsynth.service @ONLY )
|
||||
|
||||
configure_file ( fluidsynth.conf.in
|
||||
${CMAKE_BINARY_DIR}/fluidsynth.conf @ONLY )
|
||||
${FluidSynth_BINARY_DIR}/fluidsynth.conf @ONLY )
|
||||
|
||||
endif ( DEFINED FLUID_DAEMON_ENV_FILE )
|
||||
|
||||
# uninstall custom target
|
||||
configure_file ( "${CMAKE_SOURCE_DIR}/cmake_admin/cmake_uninstall.cmake.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY)
|
||||
configure_file ( "${FluidSynth_SOURCE_DIR}/cmake_admin/cmake_uninstall.cmake.in"
|
||||
"${FluidSynth_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY)
|
||||
add_custom_target ( uninstall
|
||||
"${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
|
||||
|
||||
# tarball custom target
|
||||
add_custom_target ( tarball
|
||||
COMMAND mkdir -p ${PACKAGE}-${VERSION}
|
||||
COMMAND cp -r bindings ${PACKAGE}-${VERSION}
|
||||
COMMAND cp -r cmake_admin ${PACKAGE}-${VERSION}
|
||||
COMMAND cp -r doc ${PACKAGE}-${VERSION}
|
||||
COMMAND cp -r include ${PACKAGE}-${VERSION}
|
||||
COMMAND cp -r src ${PACKAGE}-${VERSION}
|
||||
COMMAND cp AUTHORS ChangeLog CMakeLists.txt LICENSE ${PACKAGE}.* INSTALL NEWS README* THANKS TODO ${PACKAGE}-${VERSION}
|
||||
# COMMAND tar -cj --exclude .svn --exclude Makefile.am -f ${PACKAGE}-${VERSION}.tar.bz2 ${PACKAGE}-${VERSION}
|
||||
# COMMAND tar -cz --exclude .svn --exclude Makefile.am -f ${PACKAGE}-${VERSION}.tar.gz ${PACKAGE}-${VERSION}
|
||||
# COMMAND zip -qr ${PACKAGE}-${VERSION}.zip ${PACKAGE}-${VERSION} -x '*.svn*' -x '*Makefile.am'
|
||||
COMMAND tar -cj --exclude .svn -f ${PACKAGE}-${VERSION}.tar.bz2 ${PACKAGE}-${VERSION}
|
||||
COMMAND tar -cz --exclude .svn -f ${PACKAGE}-${VERSION}.tar.gz ${PACKAGE}-${VERSION}
|
||||
COMMAND zip -qr ${PACKAGE}-${VERSION}.zip ${PACKAGE}-${VERSION} -x '*.svn*'
|
||||
COMMAND rm -rf ${PACKAGE}-${VERSION}
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
)
|
||||
|
||||
"${CMAKE_COMMAND}" -P "${FluidSynth_BINARY_DIR}/cmake_uninstall.cmake")
|
||||
endif ( UNIX )
|
||||
|
||||
include ( report )
|
||||
|
@ -935,8 +927,8 @@ include ( report )
|
|||
# CPack support
|
||||
set ( CPACK_PACKAGE_DESCRIPTION_SUMMARY "FluidSynth real-time synthesizer" )
|
||||
set ( CPACK_PACKAGE_VENDOR "fluidsynth.org" )
|
||||
set ( CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_SOURCE_DIR}/README.md" )
|
||||
set ( CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSE" )
|
||||
set ( CPACK_PACKAGE_DESCRIPTION_FILE "${FluidSynth_SOURCE_DIR}/README.md" )
|
||||
set ( CPACK_RESOURCE_FILE_LICENSE "${FluidSynth_SOURCE_DIR}/LICENSE" )
|
||||
set ( CPACK_PACKAGE_VERSION_MAJOR ${FLUIDSYNTH_VERSION_MAJOR} )
|
||||
set ( CPACK_PACKAGE_VERSION_MINOR ${FLUIDSYNTH_VERSION_MINOR} )
|
||||
set ( CPACK_PACKAGE_VERSION_PATCH ${FLUIDSYNTH_VERSION_MICRO} )
|
||||
|
|
10
FluidSynthConfig.cmake.in
Normal file
10
FluidSynthConfig.cmake.in
Normal file
|
@ -0,0 +1,10 @@
|
|||
# for the find_dependency() macro:
|
||||
# include(CMakeFindDependencyMacro)
|
||||
# it has the same syntax as find_package:
|
||||
# find_dependency(MYDEP REQUIRED)
|
||||
|
||||
# define variables for configuration options:
|
||||
# set(network-enabled @enable-network@)
|
||||
|
||||
# finally, include the targets file
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/FluidSynthTargets.cmake")
|
|
@ -8,8 +8,6 @@
|
|||
| <img src="https://www.microsoft.com/windows/favicon.ico" height="25" alt=""> **Windows (vcpkg)** | [](https://dev.azure.com/tommbrt/tommbrt/_build/latest?definitionId=6&branchName=master) |
|
||||
| <img src="https://www.apple.com/favicon.ico" height="30" alt=""> **MacOSX** | [](https://dev.azure.com/tommbrt/tommbrt/_build/latest?definitionId=5&branchName=master) |
|
||||
| <img src="https://www.android.com/favicon.ico" height="30" alt=""> **Android** | [](https://dev.azure.com/tommbrt/tommbrt/_build/latest?definitionId=4&branchName=master) |
|
||||
| <img src="https://www.android.com/favicon.ico" height="30" alt=""> **Android** (legacy Cerbero) | [](https://circleci.com/gh/FluidSynth/fluidsynth) |
|
||||
|
||||
|
||||
|
||||
#### FluidSynth is a cross-platform, real-time software synthesizer based on the Soundfont 2 specification.
|
||||
|
|
|
@ -1,92 +1,56 @@
|
|||
# Provides install directory variables as defined by the GNU Coding Standards
|
||||
include ( GNUInstallDirs )
|
||||
|
||||
# Several directory names used by FluidSynth to install files
|
||||
# the variable names are similar to the KDE4 build system
|
||||
|
||||
# DEFAULT_SOUNDFONT - automatically loaded in some use cases
|
||||
if ( WIN32 )
|
||||
set (DEFAULT_SOUNDFONT "C:\\\\soundfonts\\\\default.sf2" CACHE STRING
|
||||
set (DEFAULT_SOUNDFONT "C:\\\\ProgramData\\\\soundfonts\\\\default.sf2" CACHE STRING
|
||||
"Default soundfont file")
|
||||
else ( WIN32 )
|
||||
set (DEFAULT_SOUNDFONT "${CMAKE_INSTALL_PREFIX}/share/soundfonts/default.sf2" CACHE STRING
|
||||
set (DEFAULT_SOUNDFONT "${CMAKE_INSTALL_FULL_DATADIR}/soundfonts/default.sf2" CACHE STRING
|
||||
"Default soundfont file")
|
||||
endif ( WIN32 )
|
||||
mark_as_advanced (DEFAULT_SOUNDFONT)
|
||||
|
||||
set(FRAMEWORK_INSTALL_PREFIX "")
|
||||
if ( CMAKE_VERSION VERSION_GREATER "3.7.0" AND NOT CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT )
|
||||
set(FRAMEWORK_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX})
|
||||
endif()
|
||||
|
||||
# BUNDLE_INSTALL_DIR - Mac only: the directory for application bundles
|
||||
set (BUNDLE_INSTALL_DIR "/Applications" CACHE STRING
|
||||
set (BUNDLE_INSTALL_DIR "Applications" CACHE STRING
|
||||
"The install dir for application bundles")
|
||||
mark_as_advanced (BUNDLE_INSTALL_DIR)
|
||||
|
||||
|
||||
# FRAMEWORK_INSTALL_DIR - Mac only: the directory for framework bundles
|
||||
set (FRAMEWORK_INSTALL_DIR "/Library/Frameworks" CACHE STRING
|
||||
set (FRAMEWORK_INSTALL_DIR "Library/Frameworks" CACHE STRING
|
||||
"The install dir for framework bundles")
|
||||
mark_as_advanced (FRAMEWORK_INSTALL_DIR)
|
||||
|
||||
# BIN_INSTALL_DIR - the directory where executables will be installed
|
||||
set (BIN_INSTALL_DIR "bin" CACHE STRING "The install dir for executables")
|
||||
mark_as_advanced (BIN_INSTALL_DIR)
|
||||
|
||||
# SBIN_INSTALL_DIR - the directory where system executables will be installed
|
||||
set (SBIN_INSTALL_DIR "sbin" CACHE STRING
|
||||
"The install dir for system executables")
|
||||
mark_as_advanced (SBIN_INSTALL_DIR)
|
||||
|
||||
# LIB_INSTALL_DIR - the directory where libraries will be installed
|
||||
set (LIB_INSTALL_DIR "lib${LIB_SUFFIX}" CACHE STRING "The install dir for libraries")
|
||||
mark_as_advanced (LIB_INSTALL_DIR)
|
||||
|
||||
# INCLUDE_INSTALL_DIR - the install dir for header files
|
||||
set (INCLUDE_INSTALL_DIR "include" CACHE STRING "The install dir for headers")
|
||||
mark_as_advanced (INCLUDE_INSTALL_DIR)
|
||||
|
||||
# DATA_INSTALL_DIR - the base install directory for data files
|
||||
set (DATA_INSTALL_DIR "share" CACHE STRING
|
||||
"The base install dir for data files")
|
||||
mark_as_advanced (DATA_INSTALL_DIR)
|
||||
|
||||
# DOC_INSTALL_DIR - the install dir for documentation
|
||||
set (DOC_INSTALL_DIR "share/doc" CACHE STRING
|
||||
"The install dir for documentation")
|
||||
mark_as_advanced (DOC_INSTALL_DIR)
|
||||
|
||||
# INFO_INSTALL_DIR - the info install dir
|
||||
set (INFO_INSTALL_DIR "share/info" CACHE STRING "The info install dir")
|
||||
mark_as_advanced (INFO_INSTALL_DIR)
|
||||
|
||||
# MAN_INSTALL_DIR - the man pages install dir
|
||||
if ( CMAKE_SYSTEM_NAME MATCHES "FreeBSD|DragonFly")
|
||||
set (MAN_INSTALL_DIR "man/man1" CACHE STRING "The man pages install dir")
|
||||
else()
|
||||
set (MAN_INSTALL_DIR "share/man/man1" CACHE STRING "The man pages install dir")
|
||||
endif()
|
||||
mark_as_advanced (MAN_INSTALL_DIR)
|
||||
|
||||
# SYSCONF_INSTALL_DIR - the config file install dir
|
||||
set (SYSCONF_INSTALL_DIR "/etc" CACHE PATH
|
||||
"The sysconfig install dir")
|
||||
mark_as_advanced (SYSCONF_INSTALL_DIR)
|
||||
mark_as_advanced (FRAMEWORK_INSTALL_DIR)
|
||||
|
||||
# XDG_APPS_INSTALL_DIR - the XDG apps dir, where .desktop files are installed
|
||||
set (XDG_APPS_INSTALL_DIR "share/applications" CACHE STRING "The XDG apps dir")
|
||||
set (XDG_APPS_INSTALL_DIR "${CMAKE_INSTALL_DATADIR}/applications" CACHE STRING "The XDG apps dir")
|
||||
mark_as_advanced (XDG_APPS_INSTALL_DIR)
|
||||
|
||||
# XDG_MIME_INSTALL_DIR - the XDG mimetypes install dir
|
||||
set (XDG_MIME_INSTALL_DIR "share/mime/packages" CACHE STRING
|
||||
set (XDG_MIME_INSTALL_DIR "${CMAKE_INSTALL_DATADIR}/mime/packages" CACHE STRING
|
||||
"The install dir for the xdg mimetypes")
|
||||
mark_as_advanced (XDG_MIME_INSTALL_DIR)
|
||||
|
||||
|
||||
# DBUS_INTERFACES_INSTALL_DIR - the directory where dbus interfaces are
|
||||
# installed
|
||||
set (DBUS_INTERFACES_INSTALL_DIR "share/dbus-1/interfaces" CACHE STRING
|
||||
set (DBUS_INTERFACES_INSTALL_DIR "${CMAKE_INSTALL_DATADIR}/dbus-1/interfaces" CACHE STRING
|
||||
"The dbus interfaces install dir")
|
||||
mark_as_advanced (DBUS_INTERFACES_INSTALL_DIR)
|
||||
|
||||
# DBUS_SERVICES_INSTALL_DIR - the directory where dbus services are installed
|
||||
set (DBUS_SERVICES_INSTALL_DIR "share/dbus-1/services" CACHE STRING
|
||||
set (DBUS_SERVICES_INSTALL_DIR "${CMAKE_INSTALL_DATADIR}/dbus-1/services" CACHE STRING
|
||||
"The dbus services install dir")
|
||||
mark_as_advanced (DBUS_SERVICES_INSTALL_DIR)
|
||||
|
||||
# DBUS_SYSTEM_SERVICES_INSTALL_DIR - the directory where dbus system services
|
||||
# are installed
|
||||
set (DBUS_SYSTEM_SERVICES_INSTALL_DIR "share/dbus-1/system-services"
|
||||
set (DBUS_SYSTEM_SERVICES_INSTALL_DIR "${CMAKE_INSTALL_DATADIR}/dbus-1/system-services"
|
||||
CACHE STRING "The dbus system services install dir")
|
||||
mark_as_advanced (DBUS_SYSTEM_SERVICES_INSTALL_DIR)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
macro ( ADD_FLUID_TEST _test )
|
||||
ADD_EXECUTABLE(${_test} ${_test}.c $<TARGET_OBJECTS:libfluidsynth-OBJ> )
|
||||
add_executable( ${_test} ${_test}.c )
|
||||
|
||||
# only build this unit test when explicitly requested by "make check"
|
||||
set_target_properties(${_test} PROPERTIES EXCLUDE_FROM_ALL TRUE)
|
||||
|
@ -8,7 +8,7 @@ macro ( ADD_FLUID_TEST _test )
|
|||
if ( FLUID_CPPFLAGS )
|
||||
set_target_properties ( ${_test} PROPERTIES COMPILE_FLAGS ${FLUID_CPPFLAGS} )
|
||||
endif ( FLUID_CPPFLAGS )
|
||||
TARGET_LINK_LIBRARIES(${_test} $<TARGET_PROPERTY:libfluidsynth,INTERFACE_LINK_LIBRARIES>)
|
||||
target_link_libraries( ${_test} libfluidsynth-OBJ )
|
||||
|
||||
# use the local include path to look for fluidsynth.h, as we cannot be sure fluidsynth is already installed
|
||||
target_include_directories(${_test}
|
||||
|
@ -16,7 +16,7 @@ macro ( ADD_FLUID_TEST _test )
|
|||
$<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/include> # include auto generated headers
|
||||
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/include> # include "normal" public (sub-)headers
|
||||
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/src> # include private headers
|
||||
$<TARGET_PROPERTY:libfluidsynth,INCLUDE_DIRECTORIES> # include all other header search paths needed by libfluidsynth (esp. glib)
|
||||
$<TARGET_PROPERTY:libfluidsynth-OBJ,INCLUDE_DIRECTORIES> # include all other header search paths needed by libfluidsynth (esp. glib)
|
||||
)
|
||||
|
||||
# add the test to ctest
|
||||
|
@ -28,7 +28,7 @@ macro ( ADD_FLUID_TEST _test )
|
|||
endmacro ( ADD_FLUID_TEST )
|
||||
|
||||
macro ( ADD_FLUID_TEST_UTIL _util )
|
||||
ADD_EXECUTABLE(${_util} ${_util}.c $<TARGET_OBJECTS:libfluidsynth-OBJ> )
|
||||
add_executable( ${_util} ${_util}.c )
|
||||
|
||||
# only build this unit test when explicitly requested by "make check"
|
||||
set_target_properties(${_util} PROPERTIES EXCLUDE_FROM_ALL TRUE)
|
||||
|
@ -40,7 +40,7 @@ macro ( ADD_FLUID_TEST_UTIL _util )
|
|||
if ( FLUID_CPPFLAGS )
|
||||
set_target_properties ( ${_util} PROPERTIES COMPILE_FLAGS ${FLUID_CPPFLAGS} )
|
||||
endif ( FLUID_CPPFLAGS )
|
||||
TARGET_LINK_LIBRARIES(${_util} $<TARGET_PROPERTY:libfluidsynth,INTERFACE_LINK_LIBRARIES>)
|
||||
target_link_libraries( ${_util} libfluidsynth-OBJ )
|
||||
|
||||
# use the local include path to look for fluidsynth.h, as we cannot be sure fluidsynth is already installed
|
||||
target_include_directories(${_util}
|
||||
|
@ -48,7 +48,7 @@ macro ( ADD_FLUID_TEST_UTIL _util )
|
|||
$<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/include> # include auto generated headers
|
||||
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/include> # include "normal" public (sub-)headers
|
||||
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/src> # include private headers
|
||||
$<TARGET_PROPERTY:libfluidsynth,INCLUDE_DIRECTORIES> # include all other header search paths needed by libfluidsynth (esp. glib)
|
||||
$<TARGET_PROPERTY:libfluidsynth-OBJ,INCLUDE_DIRECTORIES> # include all other header search paths needed by libfluidsynth (esp. glib)
|
||||
)
|
||||
|
||||
# append the current unit test to check-target as dependency
|
||||
|
|
75
cmake_admin/PkgConfigHelpers.cmake
Normal file
75
cmake_admin/PkgConfigHelpers.cmake
Normal file
|
@ -0,0 +1,75 @@
|
|||
macro ( sanitize_property_dirs target property )
|
||||
set(_cleandirs)
|
||||
get_target_property(_dirs ${target} ${property})
|
||||
if(_dirs)
|
||||
foreach(_d IN LISTS _dirs)
|
||||
if(EXISTS ${_d})
|
||||
list(APPEND _cleandirs ${_d})
|
||||
else()
|
||||
message(DEBUG "removing spurious directory ${_d} from property ${property} of target ${target}")
|
||||
endif()
|
||||
endforeach()
|
||||
set_property(TARGET ${target} PROPERTY ${property} ${_cleandirs})
|
||||
endif()
|
||||
endmacro ( sanitize_property_dirs )
|
||||
|
||||
macro ( sanitize_target_dirs target )
|
||||
if (TARGET ${target})
|
||||
message(DEBUG "performing sanitize_target_dirs(${target})")
|
||||
sanitize_property_dirs( ${target} INTERFACE_INCLUDE_DIRECTORIES )
|
||||
sanitize_property_dirs( ${target} INTERFACE_SYSTEM_INCLUDE_DIRECTORIES )
|
||||
sanitize_property_dirs( ${target} INTERFACE_LINK_DIRECTORIES )
|
||||
endif()
|
||||
endmacro ( sanitize_target_dirs )
|
||||
|
||||
macro ( generate_pkgconfig_spec template outfile target )
|
||||
#message(DEBUG "generate_pkgconfig_spec: ${outfile} from template: ${template}")
|
||||
if (TARGET ${target})
|
||||
# retrieve all the private libs we depend on
|
||||
get_target_property (_libs ${target} INTERFACE_LINK_LIBRARIES)
|
||||
set(_cleanlibs)
|
||||
foreach(_lib IN LISTS _libs)
|
||||
if (TARGET ${_lib})
|
||||
# All the imported PkgConfig target are explicitly added to PC_REQUIRES_PRIV.
|
||||
# Do not duplicate them into the Libs.private section, as they will be already part of Requires.private
|
||||
else()
|
||||
list(APPEND _cleanlibs ${_lib})
|
||||
endif()
|
||||
endforeach()
|
||||
list(REMOVE_DUPLICATES _cleanlibs)
|
||||
set (LIBS_PRIVATE ${_cleanlibs})
|
||||
# make a copy
|
||||
set ( LIBS_PRIVATE_WITH_PATH ${LIBS_PRIVATE} )
|
||||
|
||||
# this matches any path and any flag entries (starting with '-')
|
||||
set ( LIB_LIST_REGEX "(^(.+)\/([^\/]+)$)|(^\-.*$)" )
|
||||
# remove all entries from the list which are specified by path and which already have -l
|
||||
list ( FILTER LIBS_PRIVATE EXCLUDE REGEX ${LIB_LIST_REGEX} )
|
||||
# include only entries specifed by path
|
||||
list ( FILTER LIBS_PRIVATE_WITH_PATH INCLUDE REGEX ${LIB_LIST_REGEX} )
|
||||
|
||||
# prepend the linker flag to all entries except the ones that already have it
|
||||
list ( TRANSFORM LIBS_PRIVATE PREPEND "-l")
|
||||
list ( JOIN LIBS_PRIVATE " " LIBS_PRIVATE_JOINED )
|
||||
list ( JOIN LIBS_PRIVATE_WITH_PATH " " LIBS_PRIVATE_WITH_PATH_JOINED )
|
||||
|
||||
list ( JOIN PC_REQUIRES_PRIV " " PC_REQUIRES_PRIV_JOINED )
|
||||
|
||||
configure_file ( ${template} ${outfile} IMMEDIATE @ONLY)
|
||||
endif()
|
||||
endmacro ( generate_pkgconfig_spec )
|
||||
|
||||
macro ( unset_pkg_config _prefix )
|
||||
unset ( ${_prefix}_VERSION CACHE )
|
||||
unset ( ${_prefix}_PREFIX CACHE )
|
||||
unset ( ${_prefix}_CFLAGS CACHE )
|
||||
unset ( ${_prefix}_CFLAGS_OTHER CACHE )
|
||||
unset ( ${_prefix}_LDFLAGS CACHE )
|
||||
unset ( ${_prefix}_LDFLAGS_OTHER CACHE )
|
||||
unset ( ${_prefix}_LIBRARIES CACHE )
|
||||
unset ( ${_prefix}_INCLUDEDIR CACHE )
|
||||
unset ( ${_prefix}_INCLUDE_DIRS CACHE )
|
||||
unset ( ${_prefix}_LIBDIR CACHE )
|
||||
unset ( ${_prefix}_LIBRARY_DIRS CACHE )
|
||||
unset ( __pkg_config_checked_${_prefix} CACHE )
|
||||
endmacro ( unset_pkg_config )
|
|
@ -22,7 +22,7 @@ if( test_not_successful )
|
|||
endif( test_not_successful )
|
||||
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E compare_files ${expected_output} ${test_output}
|
||||
COMMAND ${CMAKE_COMMAND} -E compare_files --ignore-eol ${expected_output} ${test_output}
|
||||
RESULT_VARIABLE compare_not_successful
|
||||
)
|
||||
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
macro ( unset_pkg_config _prefix )
|
||||
unset ( ${_prefix}_VERSION CACHE )
|
||||
unset ( ${_prefix}_PREFIX CACHE )
|
||||
unset ( ${_prefix}_CFLAGS CACHE )
|
||||
unset ( ${_prefix}_CFLAGS_OTHER CACHE )
|
||||
unset ( ${_prefix}_LDFLAGS CACHE )
|
||||
unset ( ${_prefix}_LDFLAGS_OTHER CACHE )
|
||||
unset ( ${_prefix}_LIBRARIES CACHE )
|
||||
unset ( ${_prefix}_INCLUDEDIR CACHE )
|
||||
unset ( ${_prefix}_INCLUDE_DIRS CACHE )
|
||||
unset ( ${_prefix}_LIBDIR CACHE )
|
||||
unset ( ${_prefix}_LIBRARY_DIRS CACHE )
|
||||
unset ( __pkg_config_checked_${_prefix} CACHE )
|
||||
endmacro ( unset_pkg_config )
|
|
@ -61,6 +61,12 @@ else ( OSS_SUPPORT )
|
|||
set ( AUDIO_MIDI_REPORT "${AUDIO_MIDI_REPORT} OSS: no\n" )
|
||||
endif ( OSS_SUPPORT )
|
||||
|
||||
if ( PIPEWIRE_SUPPORT )
|
||||
set ( AUDIO_MIDI_REPORT "${AUDIO_MIDI_REPORT} PipeWire: yes\n" )
|
||||
else ( PIPEWIRE_SUPPORT )
|
||||
set ( AUDIO_MIDI_REPORT "${AUDIO_MIDI_REPORT} PipeWire: no\n" )
|
||||
endif ( PIPEWIRE_SUPPORT )
|
||||
|
||||
if ( PORTAUDIO_SUPPORT )
|
||||
set ( AUDIO_MIDI_REPORT "${AUDIO_MIDI_REPORT} PortAudio: yes\n" )
|
||||
else ( PORTAUDIO_SUPPORT )
|
||||
|
@ -240,6 +246,14 @@ else ( ENABLE_COVERAGE )
|
|||
set ( DEVEL_REPORT "${DEVEL_REPORT} Coverage: no\n" )
|
||||
endif ( ENABLE_COVERAGE )
|
||||
|
||||
if ( MSVC )
|
||||
if ( enable-static-msvcrt )
|
||||
set ( DEVEL_REPORT "${DEVEL_REPORT} Static MSVC Runtime: yes\n" )
|
||||
else ( enable-static-msvcrt )
|
||||
set ( DEVEL_REPORT "${DEVEL_REPORT} Static MSVC Runtime: no\n" )
|
||||
endif ( enable-static-msvcrt )
|
||||
endif ( MSVC )
|
||||
|
||||
message( STATUS
|
||||
"\n**************************************************************\n"
|
||||
"Build Summary:\n"
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
debian/tmp/usr/include/*
|
||||
debian/tmp/usr/lib*/*.so
|
||||
debian/tmp/usr/lib*/pkgconfig/*.pc
|
||||
debian/tmp/usr/lib/*/*.so
|
||||
debian/tmp/usr/lib/*/pkgconfig/*.pc
|
||||
debian/tmp/usr/lib/*/cmake/fluidsynth/*.cmake
|
||||
|
|
|
@ -1 +1 @@
|
|||
debian/tmp/usr/lib*/lib*.so.*
|
||||
debian/tmp/usr/lib/*/lib*.so.*
|
||||
|
|
|
@ -26,7 +26,7 @@ config.status: CMakeLists.txt
|
|||
dh_testdir
|
||||
|
||||
# Add here commands to configure the package.
|
||||
cmake -DCMAKE_INSTALL_PREFIX=/usr -DLIB_INSTALL_DIR=/usr/lib .
|
||||
cmake -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
|
||||
build: build-stamp
|
||||
build-stamp: config.status
|
||||
|
|
|
@ -5,4 +5,4 @@ Binary: fluidsynth, libfluidsynth1, libfluidsynth-dev
|
|||
Maintainer: Rui Nuno Capela <rncbc@rncbc.org>
|
||||
Architecture: any
|
||||
Standards-Version: 3.7.2
|
||||
Build-Depends: debhelper (>= 5.0.0), cmake, pkg-config, libdb-dev, libjack-dev, libasound2-dev, libsndfile-dev, libglib2.0-dev
|
||||
Build-Depends: debhelper (>= 5.0.0), cmake (>= 3.13.0), pkg-config, libdb-dev, libjack-dev, libasound2-dev, libsndfile-dev, libglib2.0-dev
|
||||
|
|
|
@ -32,7 +32,7 @@ Group: Productivity/Multimedia/Sound/Midi
|
|||
Url: http://www.fluidsynth.org/
|
||||
Source: https://github.com/FluidSynth/%{name}/archive/v%{version}.tar.gz#/%{name}-%{version}.tar.gz
|
||||
Source1000: baselibs.conf
|
||||
BuildRequires: cmake >= 3.1.0
|
||||
BuildRequires: cmake >= 3.13.0
|
||||
BuildRequires: gcc-c++
|
||||
%if 0%{?is_opensuse}
|
||||
BuildRequires: ladspa-devel
|
||||
|
@ -133,8 +133,10 @@ ln -s %{_sbindir}/service %{buildroot}%{_sbindir}/rc%{name}
|
|||
|
||||
%files devel
|
||||
%{_libdir}/lib*.so
|
||||
%{_includedir}/*
|
||||
%dir %{_libdir}/cmake/%{name}
|
||||
%{_libdir}/cmake/%{name}/*.cmake
|
||||
%{_libdir}/pkgconfig/*.pc
|
||||
%{_includedir}/*
|
||||
|
||||
%files -n libfluidsynth3
|
||||
%{_libdir}/lib*.so.*
|
||||
|
|
|
@ -45,7 +45,7 @@ endif ( DOXYGEN_FOUND )
|
|||
|
||||
if ( UNIX )
|
||||
install ( FILES fluidsynth.1
|
||||
DESTINATION ${MAN_INSTALL_DIR} )
|
||||
DESTINATION ${CMAKE_INSTALL_MANDIR}/man1 )
|
||||
endif ( UNIX )
|
||||
|
||||
add_subdirectory ( examples )
|
||||
|
|
|
@ -11,7 +11,7 @@ target_compile_options ( fluidsynth-assetloader
|
|||
PRIVATE -Wall
|
||||
PRIVATE "$<$<CONFIG:DEBUG>:-Werror>") # Only include -Werror when building debug config
|
||||
|
||||
include_directories ( ../../../include )
|
||||
target_include_directories ( fluidsynth-assetloader PRIVATE ../../../include )
|
||||
|
||||
set ( CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -L../../../dist/${ANDROID_ABI} -lfluidsynth" )
|
||||
|
||||
|
|
|
@ -28,31 +28,47 @@
|
|||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
fluid_settings_t *settings;
|
||||
fluid_synth_t *synth;
|
||||
fluid_audio_driver_t *adriver;
|
||||
fluid_settings_t *settings = NULL;
|
||||
fluid_synth_t *synth = NULL;
|
||||
fluid_audio_driver_t *adriver = NULL;
|
||||
int sfont_id;
|
||||
int i, key;
|
||||
|
||||
/* Create the settings. */
|
||||
settings = new_fluid_settings();
|
||||
if(settings == NULL)
|
||||
{
|
||||
puts("Failed to create the settings!");
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Change the settings if necessary*/
|
||||
|
||||
/* Create the synthesizer. */
|
||||
synth = new_fluid_synth(settings);
|
||||
if(synth == NULL)
|
||||
{
|
||||
puts("Failed to create the synth!");
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Load a SoundFont and reset presets (so that new instruments
|
||||
* get used from the SoundFont)
|
||||
* Depending on the size of the SoundFont, this will take some time to complete...
|
||||
*/
|
||||
sfont_id = fluid_synth_sfload(synth, "example.sf2", 1);
|
||||
if(sfont_id == FLUID_FAILED)
|
||||
{
|
||||
puts("Loading the SoundFont failed!");
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Create the audio driver. The synthesizer starts playing as soon
|
||||
as the driver is created. */
|
||||
adriver = new_fluid_audio_driver(settings, synth);
|
||||
|
||||
/* Load a SoundFont and reset presets (so that new instruments
|
||||
* get used from the SoundFont) */
|
||||
sfont_id = fluid_synth_sfload(synth, "example.sf2", 1);
|
||||
|
||||
if(sfont_id == FLUID_FAILED)
|
||||
if(adriver == NULL)
|
||||
{
|
||||
puts("Loading the SoundFont failed!");
|
||||
puts("Failed to create the audio driver!");
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
@ -61,7 +77,6 @@ int main(int argc, char **argv)
|
|||
|
||||
for(i = 0; i < 12; i++)
|
||||
{
|
||||
|
||||
/* Generate a random key */
|
||||
key = 60 + (int)(12.0f * rand() / (float) RAND_MAX);
|
||||
|
||||
|
|
|
@ -14,11 +14,6 @@ https://stackoverflow.com/a/6251757
|
|||
Developers:
|
||||
- Settings can be deprecated by adding: <deprecated>SOME TEXT</deprecated>
|
||||
- Real-time settings can be marked with <realtime>SOME OPTIONAL TEXT</realtime>.
|
||||
|
||||
ATTENTION: if you change anything in this file, make sure you also refresh
|
||||
the doxygen/fluidsettings.txt file (used by fluidsynth.org API doc build)
|
||||
and commit the results. Refresh with the following command:
|
||||
xsltproc -o doxygen/fluidsettings.txt doxygen/fluidsettings.xsl fluidsettings.xml
|
||||
-->
|
||||
<?xml-stylesheet type="text/xsl" href="fluidsettings.xsl"?>
|
||||
<fluidsettings>
|
||||
|
@ -123,8 +118,7 @@ and commit the results. Refresh with the following command:
|
|||
<type>bool</type>
|
||||
<def>0 (FALSE)</def>
|
||||
<desc>
|
||||
When set to 1 (TRUE), samples are loaded to and unloaded from memory
|
||||
on demand.
|
||||
When set to 1 (TRUE), samples are loaded to and unloaded from memory whenever presets are being selected or unselected for a MIDI channel. PROGRAM_CHANGE and PROGRAM_SELECT events are typically responsible for this.
|
||||
</desc>
|
||||
</setting>
|
||||
<setting>
|
||||
|
@ -419,7 +413,7 @@ and commit the results. Refresh with the following command:
|
|||
<min>64</min>
|
||||
<max>8192</max>
|
||||
<desc>
|
||||
The size of the audio buffers (in frames).
|
||||
This is the number of audio samples most audio drivers will request from the synth at one time. In other words, it's the amount of samples the synth is allowed to render in one go when no state changes (events) are about to happen. Because of that, specifying too big numbers here may cause MIDI events to be poorly quantized (=untimed) when a MIDI driver or the synth's API directly is used, as fluidsynth cannot determine when those events are to arrive. This issue does not matter, when using the MIDI player or the MIDI sequencer, because in this case, fluidsynth does know when events will be received.
|
||||
</desc>
|
||||
</setting>
|
||||
<setting>
|
||||
|
@ -458,6 +452,32 @@ and commit the results. Refresh with the following command:
|
|||
Selects the CoreAudio device to use.
|
||||
</desc>
|
||||
</setting>
|
||||
<setting>
|
||||
<name>coreaudio.channel-map</name>
|
||||
<type>str</type>
|
||||
<def>(empty string)</def>
|
||||
<desc>
|
||||
This setting is a comma-separated integer list that maps fluidsynth mono-channels
|
||||
to CoreAudio device output channels. Each position in the list represents the output channel
|
||||
of the CoreAudio device.
|
||||
The value of each position indicates the zero-based index of the fluidsynth
|
||||
output mono-channel to route there (i.e. the buffer index used for fluid_synth_process()).
|
||||
Additionally, the special value of -1 will turn off an output.
|
||||
<br /><br />
|
||||
For example, the default map for a single stereo output is "0,1". A value of "0,0" will
|
||||
copy the left channel to the right, a value of "1,0" will flip left and right, and a
|
||||
value of "-1,1" will play only the right channel.
|
||||
<br /><br />
|
||||
With a six-channel output device, and the synth.audio-channels and synth.audio-groups
|
||||
settings both set to "2", a channel map of "-1,-1,0,1,2,3" will result in notes from odd
|
||||
MIDI channels (audible on the first stereo channel, i.e. mono-indices 0,1) being sent to
|
||||
outputs 3 and 4, and even MIDI channels (audible on the second stereo channel, i.e. mono-indices 2,3)
|
||||
being sent to outputs 5 and 6.
|
||||
<br /><br />
|
||||
If the list specifies less than the number of available outputs channels, outputs
|
||||
beyond those specified will maintain the default channel mapping given by the CoreAudio driver.
|
||||
</desc>
|
||||
</setting>
|
||||
<setting>
|
||||
<name>dart.device</name>
|
||||
<type>str</type>
|
||||
|
@ -607,6 +627,30 @@ and commit the results. Refresh with the following command:
|
|||
Device to use for OSS audio output.
|
||||
</desc>
|
||||
</setting>
|
||||
<setting>
|
||||
<name>pipewire.media-category</name>
|
||||
<type>str</type>
|
||||
<def>Playback</def>
|
||||
<desc>
|
||||
The media category to use. This value will be passed to <code>PW_KEY_MEDIA_CATEGORY</code>, see Pipewire documentation for valid values.
|
||||
</desc>
|
||||
</setting>
|
||||
<setting>
|
||||
<name>pipewire.media-role</name>
|
||||
<type>str</type>
|
||||
<def>Music</def>
|
||||
<desc>
|
||||
The media role to use. This value will be passed to <code>PW_KEY_MEDIA_ROLE</code>, see Pipewire documentation for valid values.
|
||||
</desc>
|
||||
</setting>
|
||||
<setting>
|
||||
<name>pipewire.media-type</name>
|
||||
<type>str</type>
|
||||
<def>Audio</def>
|
||||
<desc>
|
||||
The media type to use. This value will be passed to <code>PW_KEY_MEDIA_TYPE</code>, see Pipewire documentation for valid values.
|
||||
</desc>
|
||||
</setting>
|
||||
<setting>
|
||||
<name>portaudio.device</name>
|
||||
<type>str</type>
|
||||
|
|
|
@ -7,9 +7,9 @@
|
|||
\author Josh Green
|
||||
\author David Henningsson
|
||||
\author Tom Moebert
|
||||
\author Copyright © 2003-2021 Peter Hanappe, Conrad Berhörster, Antoine Schmitt, Pedro López-Cabanillas, Josh Green, David Henningsson, Tom Moebert
|
||||
\version Revision 2.2.4
|
||||
\date 2021-11-21
|
||||
\author Copyright © 2003-2022 Peter Hanappe, Conrad Berhörster, Antoine Schmitt, Pedro López-Cabanillas, Josh Green, David Henningsson, Tom Moebert
|
||||
\version Revision 2.2.8
|
||||
\date 2022-07-10
|
||||
|
||||
All the source code examples in this document are in the public domain; you can use them as you please. This document is licensed under the Creative Commons Attribution-Share Alike 3.0 Unported License. To view a copy of this license, visit https://creativecommons.org/licenses/by-sa/3.0/ . The FluidSynth library is distributed under the GNU Lesser General Public License. A copy of the GNU Lesser General Public License is contained in the FluidSynth package; if not, visit https://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt or write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
.\" along with this program; see the file LICENSE. If not, write to
|
||||
.\" the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
.\"
|
||||
.TH FluidSynth 1 "Jan 1, 2021"
|
||||
.TH FluidSynth 1 "Jan 1, 2022"
|
||||
.\" Please update the above date whenever this man page is modified.
|
||||
.\"
|
||||
.\" Some roff macros, for reference:
|
||||
|
|
|
@ -31,7 +31,7 @@ file.
|
|||
## Introduction to LADSPA
|
||||
|
||||
You don't need to to have detailed knowledge of LADSPA to use effects with
|
||||
FluidSynth, but knowing some of it's concepts will help if you want to make the
|
||||
FluidSynth, but knowing some of the LADSPA concepts will help if you want to make the
|
||||
best use of it.
|
||||
|
||||
If you have the LADSPA SDK installed you should be able to use the `listplugins`
|
||||
|
@ -76,13 +76,13 @@ that only have a single output port and no input at all (think of noise
|
|||
generators...)
|
||||
|
||||
Also note the line `Has run_adding() Function: No`. This specifies that this
|
||||
plugin can not mix it's audio output into an output buffer, but will always
|
||||
plugin can not mix its audio output into an output buffer, but will always
|
||||
replace anything that is already there. This will become important again later
|
||||
on.
|
||||
|
||||
## FluidSynth Host Ports
|
||||
|
||||
Just as LADSPA plugins have input and output ports, FluidSynth provides it's
|
||||
Just as LADSPA plugins have input and output ports, FluidSynth provides its
|
||||
own audio ports that can be connected to plugins. On a standard stereo setup,
|
||||
the following four ports are automatically created:
|
||||
|
||||
|
@ -135,7 +135,7 @@ Please note that we only specified the path to the library
|
|||
`/usr/lib/ladspa/delay.so` when creating the "e1" effect, but not which plugin
|
||||
from the library to use. This is possible because the delay.so library contains
|
||||
only a single plugin. If you want to use a library that contains more than one
|
||||
plugin, you would need to give the plugin name as well, as we've done when
|
||||
plugin, you would need to specify the plugin name as well, as we've done when
|
||||
creating the "e2" effect. The string to use here is what is called "Plugin
|
||||
Label" in the `analyseplugin` output.
|
||||
|
||||
|
@ -230,8 +230,8 @@ send amount specified in the SoundFont.
|
|||
|
||||
If you want to replace the internal reverb or chorus effects with a LADSPA
|
||||
plugin and you want to honour the decisions made by the SoundFont designer, you
|
||||
should use the `Reverb:Send` or `Chorus:Send` ports as effect input and
|
||||
`Main:L` and `Main:R` ports as effect outputs. (See the "Example Setups" section
|
||||
should use the `Reverb:Send` or `Chorus:Send` ports as inputs to the effects and
|
||||
`Main:L` and `Main:R` ports as outputs. (See the "Example Setups" section
|
||||
below for an example on how to replace the internal reverb with a LADSPA plugin.)
|
||||
|
||||
Please note that FluidSynth uses a mono signal for both effects, that is why
|
||||
|
@ -260,17 +260,16 @@ ladspa_effect <effect-name> <library-path> [plugin-name] [--mix [gain]]
|
|||
```
|
||||
|
||||
Load the LADSPA plugin library given by `<library-path>` and create a new effect
|
||||
(i.e. an instance of a plugin). `<effect-name>` can be chosen by the user and must
|
||||
(i.e. an instance of a plugin). `<effect-name>` can be chosen by the user and must be
|
||||
unique. `<plugin-name>` is optional if the library contains only one plugin.
|
||||
|
||||
If the optional `--mix` parameter is given, then the LADSPA engine will call the
|
||||
`run_adding` interface of the plugin. This will make the effect add it's output
|
||||
to the output buffers instead of replacing them. The `--mix` parameter takes an
|
||||
`run_adding` interface of the plugin. This will tell the effect to mix its output into the output buffers instead of replacing them. The `--mix` parameter takes an
|
||||
optional float value `gain`, which will be multiplied with each sample before
|
||||
adding to the output buffers.
|
||||
|
||||
Please note that there is no command to delete a single effect once created. To
|
||||
remove effects, please use `ladspa_reset` to clear everything start from
|
||||
remove effects, please use `ladspa_reset` to clear everything and start from
|
||||
scratch.
|
||||
|
||||
Can only be called when the effect unit is not active.
|
||||
|
@ -281,8 +280,8 @@ Can only be called when the effect unit is not active.
|
|||
ladspa_buffer <buffer-name>
|
||||
```
|
||||
|
||||
Create a new audio buffer called `<buffer-name>`. The buffer is able to be used as
|
||||
mono output or mono input to an effect. Buffers can be used to connect plugins
|
||||
Create a new audio buffer called `<buffer-name>`. The buffer can be used as
|
||||
mono output or mono input for an effect. Buffers can be used to connect plugins
|
||||
between each other without overwriting the host ports with temporary data.
|
||||
|
||||
Please note that there is no command to delete a buffer. To remove buffers,
|
||||
|
@ -296,7 +295,7 @@ Can only be used when the effect unit is not active.
|
|||
ladspa_link <effect-name> <audio-port-name> <buffer-or-host-port-name>
|
||||
```
|
||||
|
||||
Connects an effect input or output port with a buffer or a host port. This
|
||||
Connects an effect input or output port to a buffer or a host port. This
|
||||
command can be called multiple times and will overwrite the previous connection
|
||||
made on that effect port.
|
||||
|
||||
|
@ -348,7 +347,7 @@ it can be started again with `ladspa_start`.
|
|||
ladspa_reset
|
||||
```
|
||||
|
||||
Deactivates the effects unit if active and clears all configuration and loaded
|
||||
Deactivates the effects unit if it is currently active and clears all configuration and loaded
|
||||
plugins.
|
||||
|
||||
|
||||
|
@ -440,7 +439,7 @@ Explaining multi-channel output in detail is out of scope for this guide. But
|
|||
using multiple output channels has an effect on the host ports that are
|
||||
available to LADSPA plugins.
|
||||
|
||||
As soon as you configure more than one audio-channel, the main audio ports will
|
||||
As soon as you configure more than one audio-group, the main audio ports will
|
||||
not be called "Main:L" and "Main:R" anymore, but will have indices added to
|
||||
their name. So if you start FluidSynth with `-o synth.audio-groups=2`, then the
|
||||
following ports will be created:
|
||||
|
@ -462,7 +461,7 @@ LADSPA is a very simple plugin architecture and only requires the ladspa.h
|
|||
header file as compile-time dependency. To build FluidSynth on non-Linux
|
||||
platform with LADSPA support, download the ladspa.h file from
|
||||
https://www.ladspa.org and place it somewhere in your compiler include path. Then
|
||||
configure and build LADSPA as you normally would.
|
||||
configure and build FluidSynth as you normally would.
|
||||
|
||||
All information in the above documentation is valid for all other platforms as
|
||||
well. Just make sure you use the file path format specific to your platform in
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
/*!
|
||||
|
||||
\page RecentChanges Recent Changes
|
||||
\section NewIn2_2_7 What's new in 2.2.7?
|
||||
|
||||
- Most getter functions of the MIDI event API are now const correct
|
||||
- fluid_event_from_midi_event() has been added
|
||||
|
||||
|
||||
\section NewIn2_2_0 What's new in 2.2.0?
|
||||
|
||||
- #fluid_file_callbacks_t <span style="color:red">now uses <code>long long</code> as file-offset type (see #fluid_long_long_t).</span><span style="color:red;font-weight:bold">This is a breaking change</span>, which allows to load SoundFonts bigger than 2GiB on Windows. This change required to bump fluidsynth's SOVERSION.
|
||||
|
|
|
@ -16,7 +16,7 @@ and a description.
|
|||
|
||||
- jack: JACK Audio Connection Kit (Linux, Mac OS X, Windows)
|
||||
- alsa: Advanced Linux Sound Architecture (Linux)
|
||||
- oss: Open Sound System (Linux, Unix)
|
||||
- oss: Open Sound System (primarily needed on BSD, rarely also Linux and Unix in general)
|
||||
- pulseaudio: PulseAudio (Linux, Mac OS X, Windows)
|
||||
- coreaudio: Apple CoreAudio (Mac OS X)
|
||||
- dsound: Microsoft DirectSound (Windows)
|
||||
|
@ -31,6 +31,7 @@ and a description.
|
|||
- file: Driver to output audio to a file
|
||||
- sdl2*: Simple DirectMedia Layer (Linux, Windows, Mac OS X, iOS, Android,
|
||||
FreeBSD, Haiku, etc.)
|
||||
- pipewire**: PipeWire (Linux)
|
||||
|
||||
The default audio driver depends on the settings with which FluidSynth was
|
||||
compiled. You can get the default driver with
|
||||
|
@ -79,4 +80,10 @@ is responsible for initializing SDL (e.g. with SDL_Init()). This must be done
|
|||
Also make sure to call SDL_Quit() after all fluidsynth instances have been
|
||||
destroyed.
|
||||
|
||||
<strong>**Note:</strong> In order to use pipeiwre as audio driver, the application
|
||||
is responsible for initializing PipeWire (e.g. with pw_init()). This must be done
|
||||
<strong>before</strong> the first call to <code>new_fluid_settings()</code>!
|
||||
Also make sure to call pw_deinit() after all fluidsynth instances have been
|
||||
destroyed.
|
||||
|
||||
*/
|
||||
|
|
|
@ -8,7 +8,7 @@ Type=notify
|
|||
NotifyAccess=main
|
||||
EnvironmentFile=@FLUID_DAEMON_ENV_FILE@
|
||||
EnvironmentFile=-%h/.config/fluidsynth
|
||||
ExecStart=@CMAKE_INSTALL_PREFIX@/@BIN_INSTALL_DIR@/fluidsynth -is $OTHER_OPTS $SOUND_FONT
|
||||
ExecStart=@CMAKE_INSTALL_FULL_BINDIR@/fluidsynth -is $OTHER_OPTS $SOUND_FONT
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target
|
||||
|
|
|
@ -117,6 +117,7 @@ FLUIDSYNTH_API void fluid_event_system_reset(fluid_event_t *evt);
|
|||
FLUIDSYNTH_API void fluid_event_unregistering(fluid_event_t *evt);
|
||||
|
||||
FLUIDSYNTH_API void fluid_event_scale(fluid_event_t *evt, double new_scale);
|
||||
FLUIDSYNTH_API int fluid_event_from_midi_event(fluid_event_t *, const fluid_midi_event_t *);
|
||||
|
||||
/* Accessing event data */
|
||||
FLUIDSYNTH_API int fluid_event_get_type(fluid_event_t *evt);
|
||||
|
|
|
@ -114,20 +114,20 @@ FLUIDSYNTH_API void delete_fluid_midi_event(fluid_midi_event_t *event);
|
|||
/** @endlifecycle */
|
||||
|
||||
FLUIDSYNTH_API int fluid_midi_event_set_type(fluid_midi_event_t *evt, int type);
|
||||
FLUIDSYNTH_API int fluid_midi_event_get_type(fluid_midi_event_t *evt);
|
||||
FLUIDSYNTH_API int fluid_midi_event_get_type(const fluid_midi_event_t *evt);
|
||||
FLUIDSYNTH_API int fluid_midi_event_set_channel(fluid_midi_event_t *evt, int chan);
|
||||
FLUIDSYNTH_API int fluid_midi_event_get_channel(fluid_midi_event_t *evt);
|
||||
FLUIDSYNTH_API int fluid_midi_event_get_key(fluid_midi_event_t *evt);
|
||||
FLUIDSYNTH_API int fluid_midi_event_get_channel(const fluid_midi_event_t *evt);
|
||||
FLUIDSYNTH_API int fluid_midi_event_get_key(const fluid_midi_event_t *evt);
|
||||
FLUIDSYNTH_API int fluid_midi_event_set_key(fluid_midi_event_t *evt, int key);
|
||||
FLUIDSYNTH_API int fluid_midi_event_get_velocity(fluid_midi_event_t *evt);
|
||||
FLUIDSYNTH_API int fluid_midi_event_get_velocity(const fluid_midi_event_t *evt);
|
||||
FLUIDSYNTH_API int fluid_midi_event_set_velocity(fluid_midi_event_t *evt, int vel);
|
||||
FLUIDSYNTH_API int fluid_midi_event_get_control(fluid_midi_event_t *evt);
|
||||
FLUIDSYNTH_API int fluid_midi_event_get_control(const fluid_midi_event_t *evt);
|
||||
FLUIDSYNTH_API int fluid_midi_event_set_control(fluid_midi_event_t *evt, int ctrl);
|
||||
FLUIDSYNTH_API int fluid_midi_event_get_value(fluid_midi_event_t *evt);
|
||||
FLUIDSYNTH_API int fluid_midi_event_get_value(const fluid_midi_event_t *evt);
|
||||
FLUIDSYNTH_API int fluid_midi_event_set_value(fluid_midi_event_t *evt, int val);
|
||||
FLUIDSYNTH_API int fluid_midi_event_get_program(fluid_midi_event_t *evt);
|
||||
FLUIDSYNTH_API int fluid_midi_event_get_program(const fluid_midi_event_t *evt);
|
||||
FLUIDSYNTH_API int fluid_midi_event_set_program(fluid_midi_event_t *evt, int val);
|
||||
FLUIDSYNTH_API int fluid_midi_event_get_pitch(fluid_midi_event_t *evt);
|
||||
FLUIDSYNTH_API int fluid_midi_event_get_pitch(const fluid_midi_event_t *evt);
|
||||
FLUIDSYNTH_API int fluid_midi_event_set_pitch(fluid_midi_event_t *evt, int val);
|
||||
FLUIDSYNTH_API int fluid_midi_event_set_sysex(fluid_midi_event_t *evt, void *data,
|
||||
int size, int dynamic);
|
||||
|
|
|
@ -34,8 +34,8 @@ extern "C" {
|
|||
*/
|
||||
FLUIDSYNTH_API
|
||||
fluid_seq_id_t fluid_sequencer_register_fluidsynth(fluid_sequencer_t *seq, fluid_synth_t *synth);
|
||||
FLUIDSYNTH_API int
|
||||
fluid_sequencer_add_midi_event_to_buffer(void *data, fluid_midi_event_t *event);
|
||||
FLUIDSYNTH_API
|
||||
int fluid_sequencer_add_midi_event_to_buffer(void *data, fluid_midi_event_t *event);
|
||||
/* @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -331,6 +331,18 @@ FLUIDSYNTH_API int fluid_synth_tuning_dump(fluid_synth_t *synth, int bank, int p
|
|||
* render real-time audio, ensure that you call these functions from a high-priority
|
||||
* thread with little to no other duties other than calling the rendering functions.
|
||||
*
|
||||
* @warning
|
||||
* If a concurrently running thread calls any other sound affecting synth function
|
||||
* (e.g. fluid_synth_noteon(), fluid_synth_cc(), etc.) it is unspecified whether the event triggered by such a call
|
||||
* will be effective in the recently synthesized audio. While this is inaudible when only requesting small chunks from the
|
||||
* synth with every call (cf. fluid_synth_get_internal_bufsize()), it will become evident when requesting larger sample chunks:
|
||||
* With larger sample chunks it will get harder for the synth to react on those spontaneously occurring events in time
|
||||
* (like events received from a MIDI driver, or directly made synth API calls).
|
||||
* In those real-time scenarios, prefer requesting smaller
|
||||
* sample chunks from the synth with each call, to avoid poor quantization of your events in the synthesized audio.
|
||||
* This issue is not applicable when using the MIDI player or sequencer for event dispatching. Also
|
||||
* refer to the documentation of \setting{audio_period-size}.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
FLUIDSYNTH_API int fluid_synth_write_s16(fluid_synth_t *synth, int len,
|
||||
|
|
|
@ -19,42 +19,14 @@
|
|||
|
||||
# CMake based build system. Pedro Lopez-Cabanillas <plcl@users.sf.net>
|
||||
|
||||
include_directories (
|
||||
${CMAKE_BINARY_DIR}
|
||||
${CMAKE_SOURCE_DIR}/src
|
||||
${CMAKE_SOURCE_DIR}/src/drivers
|
||||
${CMAKE_SOURCE_DIR}/src/synth
|
||||
${CMAKE_SOURCE_DIR}/src/rvoice
|
||||
${CMAKE_SOURCE_DIR}/src/midi
|
||||
${CMAKE_SOURCE_DIR}/src/utils
|
||||
${CMAKE_SOURCE_DIR}/src/sfloader
|
||||
${CMAKE_SOURCE_DIR}/src/bindings
|
||||
${CMAKE_SOURCE_DIR}/include
|
||||
${CMAKE_BINARY_DIR}/include
|
||||
)
|
||||
|
||||
include_directories (
|
||||
SYSTEM
|
||||
${GLIB_INCLUDE_DIRS}
|
||||
${PTHREADS_INCLUDE_DIR}
|
||||
${SDL2_INCLUDE_DIR}
|
||||
${LIBINSTPATCH_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
# ************ library ************
|
||||
|
||||
if ( READLINE_SUPPORT )
|
||||
include_directories ( ${READLINE_INCLUDE_DIR} )
|
||||
endif ( READLINE_SUPPORT )
|
||||
|
||||
if ( PULSE_SUPPORT )
|
||||
set ( fluid_pulse_SOURCES drivers/fluid_pulse.c )
|
||||
include_directories ( ${PULSE_INCLUDE_DIRS} )
|
||||
endif ( PULSE_SUPPORT )
|
||||
|
||||
if ( ALSA_SUPPORT )
|
||||
set ( fluid_alsa_SOURCES drivers/fluid_alsa.c )
|
||||
include_directories ( ${ALSA_INCLUDE_DIRS} )
|
||||
endif ( ALSA_SUPPORT )
|
||||
|
||||
if ( COREAUDIO_SUPPORT )
|
||||
|
@ -67,17 +39,19 @@ endif ( COREMIDI_SUPPORT )
|
|||
|
||||
if ( DBUS_SUPPORT )
|
||||
set ( fluid_dbus_SOURCES bindings/fluid_rtkit.c bindings/fluid_rtkit.h )
|
||||
include_directories ( ${DBUS_INCLUDE_DIRS} )
|
||||
endif ( DBUS_SUPPORT )
|
||||
|
||||
if ( JACK_SUPPORT )
|
||||
set ( fluid_jack_SOURCES drivers/fluid_jack.c )
|
||||
include_directories ( ${JACK_INCLUDE_DIRS} )
|
||||
endif ( JACK_SUPPORT )
|
||||
|
||||
if ( PIPEWIRE_SUPPORT )
|
||||
set ( fluid_pipewire_SOURCES drivers/fluid_pipewire.c )
|
||||
include_directories ( SYSTEM ${PIPEWIRE_INCLUDE_DIRS} )
|
||||
endif ( PIPEWIRE_SUPPORT )
|
||||
|
||||
if ( PORTAUDIO_SUPPORT )
|
||||
set ( fluid_portaudio_SOURCES drivers/fluid_portaudio.c )
|
||||
include_directories ( ${PORTAUDIO_INCLUDE_DIRS} )
|
||||
endif ( PORTAUDIO_SUPPORT )
|
||||
|
||||
if ( DSOUND_SUPPORT )
|
||||
|
@ -98,7 +72,6 @@ endif ( WINMIDI_SUPPORT )
|
|||
|
||||
if ( SDL2_SUPPORT )
|
||||
set ( fluid_sdl2_SOURCES drivers/fluid_sdl2.c )
|
||||
include_directories ( ${SDL2_INCLUDE_DIRS} )
|
||||
endif ( SDL2_SUPPORT )
|
||||
|
||||
if ( OSS_SUPPORT )
|
||||
|
@ -107,25 +80,14 @@ endif ( OSS_SUPPORT )
|
|||
|
||||
if ( LASH_SUPPORT )
|
||||
set ( fluid_lash_SOURCES bindings/fluid_lash.c bindings/fluid_lash.h )
|
||||
include_directories ( ${LASH_INCLUDE_DIRS})
|
||||
endif ( LASH_SUPPORT )
|
||||
|
||||
if ( SYSTEMD_SUPPORT )
|
||||
include_directories ( ${SYSTEMD_INCLUDE_DIRS})
|
||||
endif ( SYSTEMD_SUPPORT )
|
||||
|
||||
if ( DART_SUPPORT )
|
||||
set ( fluid_dart_SOURCES drivers/fluid_dart.c )
|
||||
include_directories ( ${DART_INCLUDE_DIRS} )
|
||||
endif ( DART_SUPPORT )
|
||||
|
||||
if ( LIBSNDFILE_SUPPORT )
|
||||
include_directories ( ${LIBSNDFILE_INCLUDE_DIRS} )
|
||||
endif ( LIBSNDFILE_SUPPORT )
|
||||
|
||||
if ( MIDISHARE_SUPPORT )
|
||||
set ( fluid_midishare_SOURCES drivers/fluid_midishare.c )
|
||||
include_directories ( ${MidiShare_INCLUDE_DIRS} )
|
||||
endif ( MIDISHARE_SUPPORT )
|
||||
|
||||
if ( AUFILE_SUPPORT )
|
||||
|
@ -138,15 +100,13 @@ endif ( LIBINSTPATCH_SUPPORT )
|
|||
|
||||
if ( OPENSLES_SUPPORT )
|
||||
set ( fluid_opensles_SOURCES drivers/fluid_opensles.c )
|
||||
include_directories ( ${OpenSLES_INCLUDE_DIRS} )
|
||||
endif ( OPENSLES_SUPPORT )
|
||||
|
||||
if ( OBOE_SUPPORT )
|
||||
set ( fluid_oboe_SOURCES drivers/fluid_oboe.cpp )
|
||||
include_directories ( ${OBOE_INCLUDE_DIRS} )
|
||||
endif ( OBOE_SUPPORT )
|
||||
|
||||
set ( config_SOURCES ${CMAKE_BINARY_DIR}/config.h )
|
||||
set ( config_SOURCES ${FluidSynth_BINARY_DIR}/config.h )
|
||||
|
||||
set ( libfluidsynth_SOURCES
|
||||
utils/fluid_conv.c
|
||||
|
@ -222,33 +182,41 @@ set ( libfluidsynth_SOURCES
|
|||
bindings/fluid_ladspa.h
|
||||
)
|
||||
|
||||
if ( WIN32_GLIBSTUBS )
|
||||
set( libfluidsynth_SOURCES
|
||||
${libfluidsynth_SOURCES}
|
||||
utils/win32_glibstubs.c
|
||||
utils/win32_glibstubs.h
|
||||
)
|
||||
endif ( WIN32_GLIBSTUBS )
|
||||
|
||||
set ( public_HEADERS
|
||||
${CMAKE_SOURCE_DIR}/include/fluidsynth/audio.h
|
||||
${CMAKE_SOURCE_DIR}/include/fluidsynth/event.h
|
||||
${CMAKE_SOURCE_DIR}/include/fluidsynth/gen.h
|
||||
${CMAKE_SOURCE_DIR}/include/fluidsynth/ladspa.h
|
||||
${CMAKE_SOURCE_DIR}/include/fluidsynth/log.h
|
||||
${CMAKE_SOURCE_DIR}/include/fluidsynth/midi.h
|
||||
${CMAKE_SOURCE_DIR}/include/fluidsynth/misc.h
|
||||
${CMAKE_SOURCE_DIR}/include/fluidsynth/mod.h
|
||||
${CMAKE_SOURCE_DIR}/include/fluidsynth/seq.h
|
||||
${CMAKE_SOURCE_DIR}/include/fluidsynth/seqbind.h
|
||||
${CMAKE_SOURCE_DIR}/include/fluidsynth/settings.h
|
||||
${CMAKE_SOURCE_DIR}/include/fluidsynth/sfont.h
|
||||
${CMAKE_SOURCE_DIR}/include/fluidsynth/shell.h
|
||||
${CMAKE_SOURCE_DIR}/include/fluidsynth/synth.h
|
||||
${CMAKE_SOURCE_DIR}/include/fluidsynth/types.h
|
||||
${CMAKE_SOURCE_DIR}/include/fluidsynth/voice.h
|
||||
${CMAKE_BINARY_DIR}/include/fluidsynth/version.h
|
||||
${FluidSynth_SOURCE_DIR}/include/fluidsynth/audio.h
|
||||
${FluidSynth_SOURCE_DIR}/include/fluidsynth/event.h
|
||||
${FluidSynth_SOURCE_DIR}/include/fluidsynth/gen.h
|
||||
${FluidSynth_SOURCE_DIR}/include/fluidsynth/ladspa.h
|
||||
${FluidSynth_SOURCE_DIR}/include/fluidsynth/log.h
|
||||
${FluidSynth_SOURCE_DIR}/include/fluidsynth/midi.h
|
||||
${FluidSynth_SOURCE_DIR}/include/fluidsynth/misc.h
|
||||
${FluidSynth_SOURCE_DIR}/include/fluidsynth/mod.h
|
||||
${FluidSynth_SOURCE_DIR}/include/fluidsynth/seq.h
|
||||
${FluidSynth_SOURCE_DIR}/include/fluidsynth/seqbind.h
|
||||
${FluidSynth_SOURCE_DIR}/include/fluidsynth/settings.h
|
||||
${FluidSynth_SOURCE_DIR}/include/fluidsynth/sfont.h
|
||||
${FluidSynth_SOURCE_DIR}/include/fluidsynth/shell.h
|
||||
${FluidSynth_SOURCE_DIR}/include/fluidsynth/synth.h
|
||||
${FluidSynth_SOURCE_DIR}/include/fluidsynth/types.h
|
||||
${FluidSynth_SOURCE_DIR}/include/fluidsynth/voice.h
|
||||
${FluidSynth_BINARY_DIR}/include/fluidsynth/version.h
|
||||
)
|
||||
|
||||
set ( public_main_HEADER
|
||||
${CMAKE_BINARY_DIR}/include/fluidsynth.h
|
||||
${FluidSynth_BINARY_DIR}/include/fluidsynth.h
|
||||
)
|
||||
|
||||
configure_file ( ${CMAKE_SOURCE_DIR}/include/fluidsynth/version.h.in
|
||||
${CMAKE_BINARY_DIR}/include/fluidsynth/version.h )
|
||||
configure_file ( ${CMAKE_SOURCE_DIR}/include/fluidsynth.cmake
|
||||
configure_file ( ${FluidSynth_SOURCE_DIR}/include/fluidsynth/version.h.in
|
||||
${FluidSynth_BINARY_DIR}/include/fluidsynth/version.h )
|
||||
configure_file ( ${FluidSynth_SOURCE_DIR}/include/fluidsynth.cmake
|
||||
${public_main_HEADER} )
|
||||
|
||||
if ( WIN32 )
|
||||
|
@ -277,6 +245,7 @@ add_library ( libfluidsynth-OBJ OBJECT
|
|||
${fluid_dart_SOURCES}
|
||||
${fluid_dbus_SOURCES}
|
||||
${fluid_jack_SOURCES}
|
||||
${fluid_pipewire_SOURCES}
|
||||
${fluid_lash_SOURCES}
|
||||
${fluid_midishare_SOURCES}
|
||||
${fluid_opensles_SOURCES}
|
||||
|
@ -296,18 +265,38 @@ add_library ( libfluidsynth-OBJ OBJECT
|
|||
${VersionFilesOutputVariable}
|
||||
)
|
||||
|
||||
target_include_directories ( libfluidsynth-OBJ PRIVATE
|
||||
${FluidSynth_BINARY_DIR}
|
||||
${FluidSynth_BINARY_DIR}/include
|
||||
${FluidSynth_SOURCE_DIR}/src
|
||||
${FluidSynth_SOURCE_DIR}/src/drivers
|
||||
${FluidSynth_SOURCE_DIR}/src/synth
|
||||
${FluidSynth_SOURCE_DIR}/src/rvoice
|
||||
${FluidSynth_SOURCE_DIR}/src/midi
|
||||
${FluidSynth_SOURCE_DIR}/src/utils
|
||||
${FluidSynth_SOURCE_DIR}/src/sfloader
|
||||
${FluidSynth_SOURCE_DIR}/src/bindings
|
||||
${FluidSynth_SOURCE_DIR}/include
|
||||
)
|
||||
|
||||
if ( LIBFLUID_CPPFLAGS )
|
||||
set_target_properties ( libfluidsynth-OBJ
|
||||
PROPERTIES COMPILE_FLAGS ${LIBFLUID_CPPFLAGS} )
|
||||
endif ( LIBFLUID_CPPFLAGS )
|
||||
|
||||
# note: by default this target creates a shared object (or dll). To build a
|
||||
# Note: by default this target creates a shared object (or dll). To build a
|
||||
# static library instead, set the option BUILD_SHARED_LIBS to FALSE.
|
||||
add_library ( libfluidsynth $<TARGET_OBJECTS:libfluidsynth-OBJ> )
|
||||
# Further note: The headers must be explicitly added here to have CMake install
|
||||
# them correctly in case of MACOSX_FRAMEWORK
|
||||
add_library ( libfluidsynth
|
||||
$<TARGET_OBJECTS:libfluidsynth-OBJ>
|
||||
${public_main_HEADER}
|
||||
${public_HEADERS}
|
||||
)
|
||||
|
||||
if ( MACOSX_FRAMEWORK )
|
||||
set_property ( SOURCE ${public_HEADERS}
|
||||
PROPERTY MACOSX_PACKAGE_LOCATION Headers/fluidsynth
|
||||
set_source_files_properties ( ${public_HEADERS}
|
||||
PROPERTIES MACOSX_PACKAGE_LOCATION Headers/fluidsynth
|
||||
)
|
||||
set_target_properties ( libfluidsynth
|
||||
PROPERTIES
|
||||
|
@ -348,33 +337,126 @@ else ( MACOSX_FRAMEWORK )
|
|||
)
|
||||
endif ( MACOSX_FRAMEWORK )
|
||||
|
||||
target_link_libraries ( libfluidsynth
|
||||
${GLIB_LIBRARIES}
|
||||
${GMODULE_LIBRARIES}
|
||||
${LASH_LIBRARIES}
|
||||
${JACK_LIBRARIES}
|
||||
${ALSA_LIBRARIES}
|
||||
${PULSE_LIBRARIES}
|
||||
${PORTAUDIO_LIBRARIES}
|
||||
${LIBSNDFILE_LIBRARIES}
|
||||
${SDL2_LIBRARIES}
|
||||
${DBUS_LIBRARIES}
|
||||
${READLINE_LIBS}
|
||||
# Since CMake 3.12, OBJECT libraries can be linked to with target_link_libraries().
|
||||
# See https://cmake.org/cmake/help/latest/command/target_link_libraries.html#linking-object-libraries
|
||||
# Object Libraries may "link" to other libraries to get usage requirements,
|
||||
# but since they do not have a link step nothing is done with their object files.
|
||||
target_link_libraries ( libfluidsynth-OBJ PUBLIC
|
||||
${DART_LIBS}
|
||||
${COREAUDIO_LIBS}
|
||||
${COREMIDI_LIBS}
|
||||
${WINDOWS_LIBS}
|
||||
${MidiShare_LIBS}
|
||||
${OpenSLES_LIBS}
|
||||
${OBOE_LIBRARIES}
|
||||
${LIBFLUID_LIBS}
|
||||
${LIBINSTPATCH_LIBRARIES}
|
||||
)
|
||||
|
||||
if ( TARGET OpenMP::OpenMP_C AND HAVE_OPENMP )
|
||||
target_link_libraries ( libfluidsynth-OBJ PUBLIC OpenMP::OpenMP_C )
|
||||
endif()
|
||||
|
||||
if ( TARGET PkgConfig::GLIB )
|
||||
target_link_libraries ( libfluidsynth-OBJ PUBLIC PkgConfig::GLIB )
|
||||
else()
|
||||
target_include_directories ( libfluidsynth-OBJ PUBLIC ${GLIB_INCLUDE_DIRS} )
|
||||
target_link_libraries ( libfluidsynth-OBJ PUBLIC ${GLIB_LIBRARIES} )
|
||||
endif()
|
||||
|
||||
if ( TARGET PkgConfig::LIBSNDFILE AND LIBSNDFILE_SUPPORT )
|
||||
target_link_libraries ( libfluidsynth-OBJ PUBLIC PkgConfig::LIBSNDFILE )
|
||||
endif()
|
||||
|
||||
if ( TARGET SndFile::sndfile AND LIBSNDFILE_SUPPORT )
|
||||
target_include_directories ( libfluidsynth-OBJ PRIVATE ${SndFile_INCLUDE_DIR} )
|
||||
target_link_libraries ( libfluidsynth-OBJ PUBLIC SndFile::sndfile )
|
||||
endif()
|
||||
|
||||
if ( TARGET PkgConfig::PULSE AND PULSE_SUPPORT )
|
||||
target_link_libraries ( libfluidsynth-OBJ PUBLIC PkgConfig::PULSE )
|
||||
endif()
|
||||
|
||||
if ( ALSA_SUPPORT )
|
||||
if ( TARGET PkgConfig::ALSA )
|
||||
target_link_libraries ( libfluidsynth-OBJ PUBLIC PkgConfig::ALSA )
|
||||
else()
|
||||
target_link_libraries ( libfluidsynth-OBJ PUBLIC ALSA::ALSA )
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if ( TARGET PkgConfig::PORTAUDIO AND PORTAUDIO_SUPPORT )
|
||||
target_link_libraries ( libfluidsynth-OBJ PUBLIC PkgConfig::PORTAUDIO )
|
||||
endif()
|
||||
|
||||
if ( TARGET PkgConfig::JACK AND JACK_SUPPORT )
|
||||
target_link_libraries ( libfluidsynth-OBJ PUBLIC PkgConfig::JACK )
|
||||
endif()
|
||||
|
||||
if ( TARGET PkgConfig::PIPEWIRE AND PIPEWIRE_SUPPORT )
|
||||
target_link_libraries ( libfluidsynth-OBJ PUBLIC PkgConfig::PIPEWIRE )
|
||||
endif()
|
||||
|
||||
if ( TARGET PkgConfig::LASH AND LASH_SUPPORT )
|
||||
target_link_libraries ( libfluidsynth-OBJ PUBLIC PkgConfig::LASH )
|
||||
endif()
|
||||
|
||||
if ( TARGET PkgConfig::DBUS AND DBUS_SUPPORT )
|
||||
target_link_libraries ( libfluidsynth-OBJ PUBLIC PkgConfig::DBUS )
|
||||
endif()
|
||||
|
||||
if ( TARGET PkgConfig::GMODULE AND LADSPA_SUPPORT )
|
||||
target_link_libraries ( libfluidsynth-OBJ PUBLIC PkgConfig::GMODULE )
|
||||
endif()
|
||||
|
||||
if ( TARGET PkgConfig::LIBINSTPATCH AND LIBINSTPATCH_SUPPORT )
|
||||
target_link_libraries ( libfluidsynth-OBJ PUBLIC PkgConfig::LIBINSTPATCH )
|
||||
endif()
|
||||
|
||||
if ( TARGET PkgConfig::SDL2 AND SDL2_SUPPORT )
|
||||
target_link_libraries ( libfluidsynth-OBJ PUBLIC PkgConfig::SDL2 )
|
||||
endif()
|
||||
|
||||
if ( TARGET PkgConfig::OBOE AND OBOE_SUPPORT )
|
||||
target_link_libraries ( libfluidsynth-OBJ PUBLIC PkgConfig::OBOE )
|
||||
endif()
|
||||
|
||||
if ( WITH_READLINE )
|
||||
if ( TARGET PkgConfig::READLINE )
|
||||
target_link_libraries ( libfluidsynth-OBJ PUBLIC PkgConfig::READLINE )
|
||||
else()
|
||||
target_link_libraries ( libfluidsynth-OBJ PUBLIC ${READLINE_LIBRARIES} )
|
||||
target_include_directories ( libfluidsynth-OBJ PUBLIC ${READLINE_INCLUDE_DIR} )
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if ( DART_SUPPORT )
|
||||
target_include_directories ( libfluidsynth-OBJ PUBLIC ${DART_INCLUDE_DIRS} )
|
||||
endif ( DART_SUPPORT )
|
||||
|
||||
if ( MIDISHARE_SUPPORT )
|
||||
target_include_directories ( libfluidsynth-OBJ PUBLIC ${MidiShare_INCLUDE_DIRS} )
|
||||
endif ( MIDISHARE_SUPPORT )
|
||||
|
||||
if ( OPENSLES_SUPPORT )
|
||||
target_include_directories ( libfluidsynth-OBJ PUBLIC ${OpenSLES_INCLUDE_DIRS} )
|
||||
endif ( OPENSLES_SUPPORT )
|
||||
|
||||
# This doesn't install any object file at all!
|
||||
# it is only a trick for exporting targets
|
||||
install( TARGETS libfluidsynth-OBJ
|
||||
EXPORT FluidSynthTargets
|
||||
OBJECTS )
|
||||
|
||||
# Here are applied/linked the OBJECT library dependencies
|
||||
target_link_libraries ( libfluidsynth PRIVATE libfluidsynth-OBJ )
|
||||
|
||||
# ************ CLI program ************
|
||||
|
||||
set ( fluidsynth_SOURCES fluidsynth.c )
|
||||
|
||||
if ( WIN32_GLIBSTUBS )
|
||||
set ( fluidsynth_SOURCES ${fluidsynth_SOURCES} utils/win32_glibstubs.c )
|
||||
endif ( WIN32_GLIBSTUBS )
|
||||
|
||||
if ( WASAPI_SUPPORT )
|
||||
set ( fluidsynth_SOURCES ${fluidsynth_SOURCES} fluid_wasapi_device_enumerate.c )
|
||||
endif ( WASAPI_SUPPORT )
|
||||
|
@ -391,28 +473,86 @@ if ( FLUID_CPPFLAGS )
|
|||
PROPERTIES COMPILE_FLAGS ${FLUID_CPPFLAGS} )
|
||||
endif ( FLUID_CPPFLAGS )
|
||||
|
||||
target_link_libraries ( fluidsynth
|
||||
target_include_directories ( fluidsynth PRIVATE
|
||||
${FluidSynth_BINARY_DIR}
|
||||
${FluidSynth_BINARY_DIR}/include
|
||||
${FluidSynth_SOURCE_DIR}/src/bindings
|
||||
${FluidSynth_SOURCE_DIR}/src/midi
|
||||
${FluidSynth_SOURCE_DIR}/src/rvoice
|
||||
${FluidSynth_SOURCE_DIR}/src/sfloader
|
||||
${FluidSynth_SOURCE_DIR}/src/synth
|
||||
${FluidSynth_SOURCE_DIR}/src/utils
|
||||
${FluidSynth_SOURCE_DIR}/src/
|
||||
${FluidSynth_SOURCE_DIR}/include
|
||||
)
|
||||
|
||||
target_link_libraries ( fluidsynth PRIVATE
|
||||
libfluidsynth
|
||||
${SYSTEMD_LIBRARIES}
|
||||
${FLUID_LIBS}
|
||||
)
|
||||
|
||||
if ( TARGET OpenMP::OpenMP_C AND HAVE_OPENMP )
|
||||
target_link_libraries ( fluidsynth PRIVATE OpenMP::OpenMP_C )
|
||||
endif()
|
||||
|
||||
if ( TARGET PkgConfig::SYSTEMD AND SYSTEMD_SUPPORT )
|
||||
target_link_libraries ( fluidsynth PRIVATE PkgConfig::SYSTEMD )
|
||||
endif()
|
||||
|
||||
if ( TARGET PkgConfig::GLIB ) # because g_file_test()
|
||||
target_link_libraries ( fluidsynth PRIVATE PkgConfig::GLIB )
|
||||
endif()
|
||||
|
||||
if ( TARGET PkgConfig::SDL2 AND SDL2_SUPPORT ) # because SDL_Init() etc.
|
||||
target_link_libraries ( fluidsynth PRIVATE PkgConfig::SDL2 )
|
||||
endif()
|
||||
|
||||
if ( TARGET PkgConfig::PIPEWIRE AND PIPEWIRE_SUPPORT ) # because pw_init() etc.
|
||||
target_link_libraries ( fluidsynth PRIVATE PkgConfig::PIPEWIRE )
|
||||
endif()
|
||||
|
||||
if ( TARGET PkgConfig::LIBINSTPATCH AND LIBINSTPATCH_SUPPORT )
|
||||
target_link_libraries ( fluidsynth PRIVATE PkgConfig::LIBINSTPATCH )
|
||||
endif()
|
||||
|
||||
if ( TARGET PkgConfig::LASH AND LASH_SUPPORT )
|
||||
target_link_libraries ( fluidsynth PRIVATE PkgConfig::LASH )
|
||||
endif()
|
||||
|
||||
if ( MACOSX_FRAMEWORK )
|
||||
install ( TARGETS fluidsynth libfluidsynth
|
||||
RUNTIME DESTINATION ${BIN_INSTALL_DIR}
|
||||
FRAMEWORK DESTINATION ${FRAMEWORK_INSTALL_DIR}
|
||||
ARCHIVE DESTINATION ${FRAMEWORK_INSTALL_DIR}
|
||||
EXPORT FluidSynthTargets
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
FRAMEWORK DESTINATION "${FRAMEWORK_INSTALL_PREFIX}/${FRAMEWORK_INSTALL_DIR}"
|
||||
ARCHIVE DESTINATION "${FRAMEWORK_INSTALL_PREFIX}/${FRAMEWORK_INSTALL_DIR}"
|
||||
)
|
||||
else ( MACOSX_FRAMEWORK )
|
||||
install ( TARGETS fluidsynth libfluidsynth
|
||||
RUNTIME DESTINATION ${BIN_INSTALL_DIR}
|
||||
LIBRARY DESTINATION ${LIB_INSTALL_DIR}
|
||||
ARCHIVE DESTINATION ${LIB_INSTALL_DIR}
|
||||
PUBLIC_HEADER DESTINATION ${INCLUDE_INSTALL_DIR}/fluidsynth
|
||||
EXPORT FluidSynthTargets
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/fluidsynth
|
||||
)
|
||||
install ( FILES ${public_main_HEADER} DESTINATION ${INCLUDE_INSTALL_DIR} )
|
||||
install ( FILES ${public_main_HEADER} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} )
|
||||
endif ( MACOSX_FRAMEWORK )
|
||||
|
||||
# Exported targets.
|
||||
|
||||
# build_interface: for the libfluidsynth target when imported from the build directory.
|
||||
# install_interface: for the target when imported from the installed directory.
|
||||
target_include_directories(libfluidsynth PUBLIC
|
||||
"$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include/;${PROJECT_BINARY_DIR}/include/>"
|
||||
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
|
||||
)
|
||||
|
||||
# installation of the exported targets
|
||||
install(EXPORT FluidSynthTargets
|
||||
FILE FluidSynthTargets.cmake
|
||||
NAMESPACE FluidSynth::
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/fluidsynth
|
||||
)
|
||||
|
||||
# ******* Auto Generated Lookup Tables ******
|
||||
|
||||
include(ExternalProject)
|
||||
|
@ -432,6 +572,6 @@ ExternalProject_Add(gentables
|
|||
"${CMAKE_COMMAND}" -DCMAKE_VERBOSE_MAKEFILE=${CMAKE_VERBOSE_MAKEFILE} -G "${CMAKE_GENERATOR}" -B "${GENTAB_BDIR}" "${GENTAB_SDIR}"
|
||||
BUILD_COMMAND
|
||||
"${CMAKE_COMMAND}" --build "${GENTAB_BDIR}"
|
||||
INSTALL_COMMAND ${GENTAB_BDIR}/make_tables.exe "${CMAKE_BINARY_DIR}/"
|
||||
INSTALL_COMMAND ${GENTAB_BDIR}/make_tables.exe "${FluidSynth_BINARY_DIR}/"
|
||||
)
|
||||
add_dependencies(libfluidsynth-OBJ gentables)
|
||||
|
|
|
@ -441,14 +441,14 @@ fluid_command(fluid_cmd_handler_t *handler, const char *cmd, fluid_ostream_t out
|
|||
return 1;
|
||||
}
|
||||
|
||||
if(!g_shell_parse_argv(cmd, &num_tokens, &tokens, NULL))
|
||||
if(!fluid_shell_parse_argv(cmd, &num_tokens, &tokens))
|
||||
{
|
||||
fluid_ostream_printf(out, "Error parsing command\n");
|
||||
return FLUID_FAILED;
|
||||
}
|
||||
|
||||
result = fluid_cmd_handler_handle(handler, num_tokens, &tokens[0], out);
|
||||
g_strfreev(tokens);
|
||||
fluid_strfreev(tokens);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -199,6 +199,7 @@ new_fluid_file_renderer(fluid_synth_t *synth)
|
|||
double samplerate;
|
||||
int retval;
|
||||
#endif
|
||||
int audio_channels;
|
||||
char *filename = NULL;
|
||||
fluid_file_renderer_t *dev;
|
||||
|
||||
|
@ -233,6 +234,7 @@ new_fluid_file_renderer(fluid_synth_t *synth)
|
|||
}
|
||||
|
||||
fluid_settings_dupstr(synth->settings, "audio.file.name", &filename);
|
||||
fluid_settings_getint(synth->settings, "synth.audio-channels", &audio_channels);
|
||||
|
||||
if(filename == NULL)
|
||||
{
|
||||
|
@ -310,6 +312,11 @@ new_fluid_file_renderer(fluid_synth_t *synth)
|
|||
|
||||
#endif
|
||||
|
||||
if(audio_channels != 1)
|
||||
{
|
||||
FLUID_LOG(FLUID_WARN, "The file-renderer currently only supports a single stereo channel. You have provided %d stereo channels. Audio may sound strange or incomplete.", audio_channels);
|
||||
}
|
||||
|
||||
FLUID_FREE(filename);
|
||||
return dev;
|
||||
|
||||
|
|
|
@ -509,8 +509,8 @@ int fluid_ladspa_reset(fluid_ladspa_fx_t *fx)
|
|||
* @param block_count number of blocks to render
|
||||
* @param block_size number of samples in a block
|
||||
*
|
||||
* FluidSynth calls this function during main output mixing, just after
|
||||
* the internal reverb and chorus effects have been processed.
|
||||
* FluidSynth calls this function during main output mixing,
|
||||
* just before processing the internal reverb and chorus effects.
|
||||
*
|
||||
* It copies audio data from the supplied buffers, runs all effects and copies the
|
||||
* resulting audio back into the same buffers.
|
||||
|
|
|
@ -130,6 +130,9 @@
|
|||
/* Define to enable JACK driver */
|
||||
#cmakedefine JACK_SUPPORT @JACK_SUPPORT@
|
||||
|
||||
/* Define to enable PipeWire driver */
|
||||
#cmakedefine PIPEWIRE_SUPPORT @PIPEWIRE_SUPPORT@
|
||||
|
||||
/* Include the LADSPA Fx unit */
|
||||
#cmakedefine LADSPA @LADSPA_SUPPORT@
|
||||
|
||||
|
@ -265,4 +268,7 @@
|
|||
/* Define to 1 if you have the socklen_t type. */
|
||||
#cmakedefine HAVE_SOCKLEN_T @HAVE_SOCKLEN_T@
|
||||
|
||||
/* Define if using glib stubs instead of real glib. */
|
||||
#cmakedefine WITH_GLIB_STUBS
|
||||
|
||||
#endif /* CONFIG_H */
|
||||
|
|
|
@ -70,6 +70,16 @@ static const fluid_audriver_definition_t fluid_audio_drivers[] =
|
|||
},
|
||||
#endif
|
||||
|
||||
#if PIPEWIRE_SUPPORT
|
||||
{
|
||||
"pipewire",
|
||||
new_fluid_pipewire_audio_driver,
|
||||
new_fluid_pipewire_audio_driver2,
|
||||
delete_fluid_pipewire_audio_driver,
|
||||
fluid_pipewire_audio_driver_settings
|
||||
},
|
||||
#endif
|
||||
|
||||
#if OSS_SUPPORT
|
||||
{
|
||||
"oss",
|
||||
|
@ -310,8 +320,9 @@ find_fluid_audio_driver(fluid_settings_t *settings)
|
|||
* Otherwise the behaviour is undefined.
|
||||
*
|
||||
* @note As soon as an audio driver is created, the \p synth starts rendering audio.
|
||||
* This means that all necessary sound-setup should be completed after this point,
|
||||
* thus of all object types in use (synth, midi player, sequencer, etc.) the audio
|
||||
* This means that all necessary initialization and sound-setup should have been
|
||||
* completed before calling this function.
|
||||
* Thus, of all object types in use (synth, midi player, sequencer, etc.) the audio
|
||||
* driver should always be the last one to be created and the first one to be deleted!
|
||||
* Also refer to the order of object creation in the code examples.
|
||||
*/
|
||||
|
@ -322,7 +333,20 @@ new_fluid_audio_driver(fluid_settings_t *settings, fluid_synth_t *synth)
|
|||
|
||||
if(def)
|
||||
{
|
||||
fluid_audio_driver_t *driver = (*def->new)(settings, synth);
|
||||
fluid_audio_driver_t *driver;
|
||||
double srate, midi_event_latency;
|
||||
int period_size;
|
||||
|
||||
fluid_settings_getint(settings, "audio.period-size", &period_size);
|
||||
fluid_settings_getnum(settings, "synth.sample-rate", &srate);
|
||||
|
||||
midi_event_latency = period_size / srate;
|
||||
if(midi_event_latency >= 0.05)
|
||||
{
|
||||
FLUID_LOG(FLUID_WARN, "You have chosen 'audio.period-size' to be %d samples. Given a sample rate of %.1f this results in a latency of %.1f ms, which will cause MIDI events to be poorly quantized (=untimed) in the synthesized audio (also known as the 'drunken-drummer' syndrome). To avoid that, you're strongly advised to increase 'audio.periods' instead, while keeping 'audio.period-size' small enough to make this warning disappear.", period_size, srate, midi_event_latency*1000.0);
|
||||
}
|
||||
|
||||
driver = (*def->new)(settings, synth);
|
||||
|
||||
if(driver)
|
||||
{
|
||||
|
|
|
@ -23,6 +23,10 @@
|
|||
|
||||
#include "fluidsynth_priv.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* fluid_audio_driver_t
|
||||
*/
|
||||
|
@ -138,6 +142,14 @@ void fluid_jack_audio_driver_settings(fluid_settings_t *settings);
|
|||
int fluid_jack_obtain_synth(fluid_settings_t *settings, fluid_synth_t **synth);
|
||||
#endif
|
||||
|
||||
#if PIPEWIRE_SUPPORT
|
||||
fluid_audio_driver_t *new_fluid_pipewire_audio_driver(fluid_settings_t *settings, fluid_synth_t *synth);
|
||||
fluid_audio_driver_t *new_fluid_pipewire_audio_driver2(fluid_settings_t *settings,
|
||||
fluid_audio_func_t func, void *data);
|
||||
void delete_fluid_pipewire_audio_driver(fluid_audio_driver_t *p);
|
||||
void fluid_pipewire_audio_driver_settings(fluid_settings_t *settings);
|
||||
#endif
|
||||
|
||||
#if SNDMAN_SUPPORT
|
||||
fluid_audio_driver_t *new_fluid_sndmgr_audio_driver(fluid_settings_t *settings,
|
||||
fluid_synth_t *synth);
|
||||
|
@ -167,6 +179,8 @@ fluid_audio_driver_t *new_fluid_file_audio_driver(fluid_settings_t *settings,
|
|||
void delete_fluid_file_audio_driver(fluid_audio_driver_t *p);
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _FLUID_AUDRIVER_H */
|
||||
|
|
|
@ -553,7 +553,7 @@ static fluid_thread_return_t fluid_alsa_audio_run_s16(void *d)
|
|||
{
|
||||
FLUID_MEMSET(left, 0, buffer_size * sizeof(*left));
|
||||
FLUID_MEMSET(right, 0, buffer_size * sizeof(*right));
|
||||
|
||||
|
||||
(*dev->callback)(dev->data, buffer_size, 0, NULL, 2, handle);
|
||||
|
||||
/* convert floating point data to 16 bit (with dithering) */
|
||||
|
@ -1347,6 +1347,26 @@ fluid_alsa_seq_run(void *d)
|
|||
}
|
||||
break;
|
||||
|
||||
case SND_SEQ_EVENT_START:
|
||||
evt.type = MIDI_START;
|
||||
break;
|
||||
|
||||
case SND_SEQ_EVENT_CONTINUE:
|
||||
evt.type = MIDI_CONTINUE;
|
||||
break;
|
||||
|
||||
case SND_SEQ_EVENT_STOP:
|
||||
evt.type = MIDI_STOP;
|
||||
break;
|
||||
|
||||
case SND_SEQ_EVENT_CLOCK:
|
||||
evt.type = MIDI_SYNC;
|
||||
break;
|
||||
|
||||
case SND_SEQ_EVENT_RESET:
|
||||
evt.type = MIDI_SYSTEM_RESET;
|
||||
break;
|
||||
|
||||
default:
|
||||
continue; /* unhandled event, next loop iteration */
|
||||
}
|
||||
|
|
|
@ -39,7 +39,6 @@
|
|||
typedef struct
|
||||
{
|
||||
fluid_audio_driver_t driver;
|
||||
fluid_audio_func_t callback;
|
||||
void *data;
|
||||
fluid_file_renderer_t *renderer;
|
||||
int period_size;
|
||||
|
@ -49,7 +48,7 @@ typedef struct
|
|||
} fluid_file_audio_driver_t;
|
||||
|
||||
|
||||
static int fluid_file_audio_run_s16(void *d, unsigned int msec);
|
||||
static int fluid_file_audio_run(void *d, unsigned int msec);
|
||||
|
||||
/**************************************************************
|
||||
*
|
||||
|
@ -78,7 +77,6 @@ new_fluid_file_audio_driver(fluid_settings_t *settings,
|
|||
fluid_settings_getnum(settings, "synth.sample-rate", &dev->sample_rate);
|
||||
|
||||
dev->data = synth;
|
||||
dev->callback = (fluid_audio_func_t) fluid_synth_process;
|
||||
dev->samples = 0;
|
||||
|
||||
dev->renderer = new_fluid_file_renderer(synth);
|
||||
|
@ -89,7 +87,7 @@ new_fluid_file_audio_driver(fluid_settings_t *settings,
|
|||
}
|
||||
|
||||
msec = (int)(0.5 + dev->period_size / dev->sample_rate * 1000.0);
|
||||
dev->timer = new_fluid_timer(msec, fluid_file_audio_run_s16, (void *) dev, TRUE, FALSE, TRUE);
|
||||
dev->timer = new_fluid_timer(msec, fluid_file_audio_run, (void *) dev, TRUE, FALSE, TRUE);
|
||||
|
||||
if(dev->timer == NULL)
|
||||
{
|
||||
|
@ -115,7 +113,7 @@ void delete_fluid_file_audio_driver(fluid_audio_driver_t *p)
|
|||
FLUID_FREE(dev);
|
||||
}
|
||||
|
||||
static int fluid_file_audio_run_s16(void *d, unsigned int clock_time)
|
||||
static int fluid_file_audio_run(void *d, unsigned int clock_time)
|
||||
{
|
||||
fluid_file_audio_driver_t *dev = (fluid_file_audio_driver_t *) d;
|
||||
unsigned int sample_time;
|
||||
|
|
|
@ -27,10 +27,10 @@
|
|||
#include "fluid_adriver.h"
|
||||
#include "fluid_settings.h"
|
||||
|
||||
/*
|
||||
/*
|
||||
* !!! Make sure that no include above includes <netinet/tcp.h> !!!
|
||||
* It #defines some macros that collide with enum definitions of OpenTransportProviders.h, which is included from OSServices.h, included from CoreServices.h
|
||||
*
|
||||
*
|
||||
* https://trac.macports.org/ticket/36962
|
||||
*/
|
||||
|
||||
|
@ -52,7 +52,8 @@ typedef struct
|
|||
fluid_audio_func_t callback;
|
||||
void *data;
|
||||
unsigned int buffer_size;
|
||||
float *buffers[2];
|
||||
unsigned int buffer_count;
|
||||
float **buffers;
|
||||
double phase;
|
||||
} fluid_core_audio_driver_t;
|
||||
|
||||
|
@ -73,6 +74,10 @@ OSStatus fluid_core_audio_callback(void *data,
|
|||
|
||||
#define OK(x) (x == noErr)
|
||||
|
||||
#if __MAC_OS_X_VERSION_MAX_ALLOWED < 120000
|
||||
#define kAudioObjectPropertyElementMain (kAudioObjectPropertyElementMaster)
|
||||
#endif
|
||||
|
||||
int
|
||||
get_num_outputs(AudioDeviceID deviceID)
|
||||
{
|
||||
|
@ -81,7 +86,7 @@ get_num_outputs(AudioDeviceID deviceID)
|
|||
AudioObjectPropertyAddress pa;
|
||||
pa.mSelector = kAudioDevicePropertyStreamConfiguration;
|
||||
pa.mScope = kAudioDevicePropertyScopeOutput;
|
||||
pa.mElement = kAudioObjectPropertyElementMaster;
|
||||
pa.mElement = kAudioObjectPropertyElementMain;
|
||||
|
||||
if(OK(AudioObjectGetPropertyDataSize(deviceID, &pa, 0, 0, &size)) && size > 0)
|
||||
{
|
||||
|
@ -110,6 +115,76 @@ get_num_outputs(AudioDeviceID deviceID)
|
|||
return total;
|
||||
}
|
||||
|
||||
void
|
||||
set_channel_map(AudioUnit outputUnit, int audio_channels, const char *map_string)
|
||||
{
|
||||
OSStatus status;
|
||||
long int number_of_channels;
|
||||
int i, *channel_map;
|
||||
UInt32 property_size;
|
||||
Boolean writable = false;
|
||||
|
||||
status = AudioUnitGetPropertyInfo(outputUnit,
|
||||
kAudioOutputUnitProperty_ChannelMap,
|
||||
kAudioUnitScope_Output,
|
||||
0,
|
||||
&property_size, &writable);
|
||||
if(status != noErr)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Failed to get the channel map size. Status=%ld\n", (long int) status);
|
||||
return;
|
||||
}
|
||||
|
||||
number_of_channels = property_size / sizeof(int);
|
||||
if(!number_of_channels)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
channel_map = FLUID_ARRAY(int, number_of_channels);
|
||||
if(channel_map == NULL)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Out of memory.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
FLUID_MEMSET(channel_map, 0xff, property_size);
|
||||
|
||||
status = AudioUnitGetProperty(outputUnit,
|
||||
kAudioOutputUnitProperty_ChannelMap,
|
||||
kAudioUnitScope_Output,
|
||||
0,
|
||||
channel_map, &property_size);
|
||||
if(status != noErr)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Failed to get the existing channel map. Status=%ld\n", (long int) status);
|
||||
FLUID_FREE(channel_map);
|
||||
return;
|
||||
}
|
||||
|
||||
fluid_settings_split_csv(map_string, channel_map, (int) number_of_channels);
|
||||
for(i = 0; i < number_of_channels; i++)
|
||||
{
|
||||
if(channel_map[i] < -1 || channel_map[i] >= audio_channels)
|
||||
{
|
||||
FLUID_LOG(FLUID_DBG, "Channel map of output channel %d is out-of-range. Silencing.", i);
|
||||
channel_map[i] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
status = AudioUnitSetProperty(outputUnit,
|
||||
kAudioOutputUnitProperty_ChannelMap,
|
||||
kAudioUnitScope_Output,
|
||||
0,
|
||||
channel_map, property_size);
|
||||
if(status != noErr)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Failed to set the channel map. Status=%ld\n", (long int) status);
|
||||
}
|
||||
|
||||
FLUID_FREE(channel_map);
|
||||
}
|
||||
|
||||
void
|
||||
fluid_core_audio_driver_settings(fluid_settings_t *settings)
|
||||
{
|
||||
|
@ -118,9 +193,10 @@ fluid_core_audio_driver_settings(fluid_settings_t *settings)
|
|||
AudioObjectPropertyAddress pa;
|
||||
pa.mSelector = kAudioHardwarePropertyDevices;
|
||||
pa.mScope = kAudioObjectPropertyScopeWildcard;
|
||||
pa.mElement = kAudioObjectPropertyElementMaster;
|
||||
pa.mElement = kAudioObjectPropertyElementMain;
|
||||
|
||||
fluid_settings_register_str(settings, "audio.coreaudio.device", "default", 0);
|
||||
fluid_settings_register_str(settings, "audio.coreaudio.channel-map", "", 0);
|
||||
fluid_settings_add_option(settings, "audio.coreaudio.device", "default");
|
||||
|
||||
if(OK(AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &pa, 0, 0, &size)))
|
||||
|
@ -165,13 +241,21 @@ new_fluid_core_audio_driver(fluid_settings_t *settings, fluid_synth_t *synth)
|
|||
fluid_audio_driver_t *
|
||||
new_fluid_core_audio_driver2(fluid_settings_t *settings, fluid_audio_func_t func, void *data)
|
||||
{
|
||||
char *devname = NULL;
|
||||
char *devname = NULL, *channel_map = NULL;
|
||||
fluid_core_audio_driver_t *dev = NULL;
|
||||
int period_size, periods;
|
||||
int period_size, periods, audio_channels = 1;
|
||||
double sample_rate;
|
||||
OSStatus status;
|
||||
UInt32 size;
|
||||
int i;
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
|
||||
ComponentDescription desc;
|
||||
Component comp;
|
||||
#else
|
||||
AudioComponentDescription desc;
|
||||
AudioComponent comp;
|
||||
#endif
|
||||
AURenderCallbackStruct render;
|
||||
|
||||
dev = FLUID_NEW(fluid_core_audio_driver_t);
|
||||
|
||||
|
@ -187,11 +271,6 @@ new_fluid_core_audio_driver2(fluid_settings_t *settings, fluid_audio_func_t func
|
|||
dev->data = data;
|
||||
|
||||
// Open the default output unit
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
|
||||
ComponentDescription desc;
|
||||
#else
|
||||
AudioComponentDescription desc;
|
||||
#endif
|
||||
desc.componentType = kAudioUnitType_Output;
|
||||
desc.componentSubType = kAudioUnitSubType_HALOutput; //kAudioUnitSubType_DefaultOutput;
|
||||
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
|
||||
|
@ -199,9 +278,9 @@ new_fluid_core_audio_driver2(fluid_settings_t *settings, fluid_audio_func_t func
|
|||
desc.componentFlagsMask = 0;
|
||||
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
|
||||
Component comp = FindNextComponent(NULL, &desc);
|
||||
comp = FindNextComponent(NULL, &desc);
|
||||
#else
|
||||
AudioComponent comp = AudioComponentFindNext(NULL, &desc);
|
||||
comp = AudioComponentFindNext(NULL, &desc);
|
||||
#endif
|
||||
|
||||
if(comp == NULL)
|
||||
|
@ -223,7 +302,6 @@ new_fluid_core_audio_driver2(fluid_settings_t *settings, fluid_audio_func_t func
|
|||
}
|
||||
|
||||
// Set up a callback function to generate output
|
||||
AURenderCallbackStruct render;
|
||||
render.inputProc = fluid_core_audio_callback;
|
||||
render.inputProcRefCon = (void *) dev;
|
||||
status = AudioUnitSetProperty(dev->outputUnit,
|
||||
|
@ -239,10 +317,14 @@ new_fluid_core_audio_driver2(fluid_settings_t *settings, fluid_audio_func_t func
|
|||
goto error_recovery;
|
||||
}
|
||||
|
||||
fluid_settings_getint(settings, "synth.audio-channels", &audio_channels);
|
||||
fluid_settings_getnum(settings, "synth.sample-rate", &sample_rate);
|
||||
fluid_settings_getint(settings, "audio.periods", &periods);
|
||||
fluid_settings_getint(settings, "audio.period-size", &period_size);
|
||||
|
||||
/* audio channels are in stereo, with a minimum of one pair */
|
||||
audio_channels = (audio_channels > 0) ? (2 * audio_channels) : 2;
|
||||
|
||||
/* get the selected device name. if none is specified, use NULL for the default device. */
|
||||
if(fluid_settings_dupstr(settings, "audio.coreaudio.device", &devname) == FLUID_OK /* alloc device name */
|
||||
&& devname && strlen(devname) > 0)
|
||||
|
@ -250,7 +332,7 @@ new_fluid_core_audio_driver2(fluid_settings_t *settings, fluid_audio_func_t func
|
|||
AudioObjectPropertyAddress pa;
|
||||
pa.mSelector = kAudioHardwarePropertyDevices;
|
||||
pa.mScope = kAudioObjectPropertyScopeWildcard;
|
||||
pa.mElement = kAudioObjectPropertyElementMaster;
|
||||
pa.mElement = kAudioObjectPropertyElementMain;
|
||||
|
||||
if(OK(AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &pa, 0, 0, &size)))
|
||||
{
|
||||
|
@ -297,11 +379,11 @@ new_fluid_core_audio_driver2(fluid_settings_t *settings, fluid_audio_func_t func
|
|||
// necessary from our format to the device's format.
|
||||
dev->format.mSampleRate = sample_rate; // sample rate of the audio stream
|
||||
dev->format.mFormatID = kAudioFormatLinearPCM; // encoding type of the audio stream
|
||||
dev->format.mFormatFlags = kLinearPCMFormatFlagIsFloat;
|
||||
dev->format.mBytesPerPacket = 2 * sizeof(float);
|
||||
dev->format.mFormatFlags = kLinearPCMFormatFlagIsFloat | kAudioFormatFlagIsNonInterleaved;
|
||||
dev->format.mBytesPerPacket = sizeof(float);
|
||||
dev->format.mFramesPerPacket = 1;
|
||||
dev->format.mBytesPerFrame = 2 * sizeof(float);
|
||||
dev->format.mChannelsPerFrame = 2;
|
||||
dev->format.mBytesPerFrame = sizeof(float);
|
||||
dev->format.mChannelsPerFrame = audio_channels;
|
||||
dev->format.mBitsPerChannel = 8 * sizeof(float);
|
||||
|
||||
FLUID_LOG(FLUID_DBG, "mSampleRate %g", dev->format.mSampleRate);
|
||||
|
@ -325,6 +407,13 @@ new_fluid_core_audio_driver2(fluid_settings_t *settings, fluid_audio_func_t func
|
|||
goto error_recovery;
|
||||
}
|
||||
|
||||
if(fluid_settings_dupstr(settings, "audio.coreaudio.channel-map", &channel_map) == FLUID_OK /* alloc channel map */
|
||||
&& channel_map && strlen(channel_map) > 0)
|
||||
{
|
||||
set_channel_map(dev->outputUnit, audio_channels, channel_map);
|
||||
}
|
||||
FLUID_FREE(channel_map); /* free channel map */
|
||||
|
||||
status = AudioUnitSetProperty(dev->outputUnit,
|
||||
kAudioUnitProperty_MaximumFramesPerSlice,
|
||||
kAudioUnitScope_Input,
|
||||
|
@ -340,15 +429,16 @@ new_fluid_core_audio_driver2(fluid_settings_t *settings, fluid_audio_func_t func
|
|||
|
||||
FLUID_LOG(FLUID_DBG, "MaximumFramesPerSlice = %d", dev->buffer_size);
|
||||
|
||||
dev->buffers[0] = FLUID_ARRAY(float, dev->buffer_size);
|
||||
dev->buffers[1] = FLUID_ARRAY(float, dev->buffer_size);
|
||||
|
||||
if(dev->buffers[0] == NULL || dev->buffers[1] == NULL)
|
||||
dev->buffers = FLUID_ARRAY(float *, audio_channels);
|
||||
|
||||
if(dev->buffers == NULL)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Out of memory.");
|
||||
goto error_recovery;
|
||||
}
|
||||
|
||||
dev->buffer_count = (unsigned int) audio_channels;
|
||||
|
||||
// Initialize the audio unit
|
||||
status = AudioUnitInitialize(dev->outputUnit);
|
||||
|
||||
|
@ -390,14 +480,9 @@ delete_fluid_core_audio_driver(fluid_audio_driver_t *p)
|
|||
AudioComponentInstanceDispose(dev->outputUnit);
|
||||
#endif
|
||||
|
||||
if(dev->buffers[0])
|
||||
if(dev->buffers != NULL)
|
||||
{
|
||||
FLUID_FREE(dev->buffers[0]);
|
||||
}
|
||||
|
||||
if(dev->buffers[1])
|
||||
{
|
||||
FLUID_FREE(dev->buffers[1]);
|
||||
FLUID_FREE(dev->buffers);
|
||||
}
|
||||
|
||||
FLUID_FREE(dev);
|
||||
|
@ -411,30 +496,18 @@ fluid_core_audio_callback(void *data,
|
|||
UInt32 inNumberFrames,
|
||||
AudioBufferList *ioData)
|
||||
{
|
||||
int i, k;
|
||||
fluid_core_audio_driver_t *dev = (fluid_core_audio_driver_t *) data;
|
||||
int len = inNumberFrames;
|
||||
float *buffer = ioData->mBuffers[0].mData;
|
||||
UInt32 i, nBuffers = ioData->mNumberBuffers;
|
||||
fluid_audio_func_t callback = (dev->callback != NULL) ? dev->callback : (fluid_audio_func_t) fluid_synth_process;
|
||||
|
||||
if(dev->callback)
|
||||
for(i = 0; i < ioData->mNumberBuffers && i < dev->buffer_count; i++)
|
||||
{
|
||||
float *left = dev->buffers[0];
|
||||
float *right = dev->buffers[1];
|
||||
|
||||
FLUID_MEMSET(left, 0, len * sizeof(float));
|
||||
FLUID_MEMSET(right, 0, len * sizeof(float));
|
||||
|
||||
(*dev->callback)(dev->data, len, 0, NULL, 2, dev->buffers);
|
||||
|
||||
for(i = 0, k = 0; i < len; i++)
|
||||
{
|
||||
buffer[k++] = left[i];
|
||||
buffer[k++] = right[i];
|
||||
}
|
||||
dev->buffers[i] = ioData->mBuffers[i].mData;
|
||||
FLUID_MEMSET(dev->buffers[i], 0, len * sizeof(float));
|
||||
}
|
||||
else
|
||||
fluid_synth_write_float((fluid_synth_t *) dev->data, len, buffer, 0, 2,
|
||||
buffer, 1, 2);
|
||||
|
||||
callback(dev->data, len, nBuffers, dev->buffers, nBuffers, dev->buffers);
|
||||
|
||||
return noErr;
|
||||
}
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
/* End work around */
|
||||
|
||||
#include <unistd.h>
|
||||
#include <os/log.h>
|
||||
#include <CoreServices/CoreServices.h>
|
||||
#include <CoreMIDI/MIDIServices.h>
|
||||
|
||||
|
@ -62,6 +63,10 @@ typedef struct
|
|||
int autoconn_inputs;
|
||||
} fluid_coremidi_driver_t;
|
||||
|
||||
static const MIDIClientRef invalid_client = (MIDIClientRef)-1;
|
||||
static const MIDIEndpointRef invalid_endpoint = (MIDIEndpointRef)-1;
|
||||
static const MIDIPortRef invalid_port = (MIDIPortRef)-1;
|
||||
|
||||
void fluid_coremidi_callback(const MIDIPacketList *list, void *p, void *src);
|
||||
|
||||
void fluid_coremidi_driver_settings(fluid_settings_t *settings)
|
||||
|
@ -108,6 +113,8 @@ new_fluid_coremidi_driver(fluid_settings_t *settings, handle_midi_event_func_t h
|
|||
char *id;
|
||||
CFStringRef str_portname;
|
||||
CFStringRef str_clientname;
|
||||
OSStatus result;
|
||||
CFStringRef str_input_portname;
|
||||
|
||||
/* not much use doing anything */
|
||||
if(handler == NULL)
|
||||
|
@ -124,9 +131,10 @@ new_fluid_coremidi_driver(fluid_settings_t *settings, handle_midi_event_func_t h
|
|||
return NULL;
|
||||
}
|
||||
|
||||
dev->client = 0;
|
||||
dev->endpoint = 0;
|
||||
dev->parser = 0;
|
||||
dev->client = invalid_client;
|
||||
dev->endpoint = invalid_endpoint;
|
||||
dev->input_port = invalid_port;
|
||||
dev->parser = NULL;
|
||||
dev->driver.handler = handler;
|
||||
dev->driver.data = data;
|
||||
|
||||
|
@ -173,7 +181,7 @@ new_fluid_coremidi_driver(fluid_settings_t *settings, handle_midi_event_func_t h
|
|||
FLUID_FREE(portname); /* -- free port name */
|
||||
}
|
||||
|
||||
OSStatus result = MIDIClientCreate(str_clientname, NULL, NULL, &client);
|
||||
result = MIDIClientCreate(str_clientname, NULL, NULL, &client);
|
||||
CFRelease(str_clientname);
|
||||
|
||||
if(result != noErr)
|
||||
|
@ -194,7 +202,7 @@ new_fluid_coremidi_driver(fluid_settings_t *settings, handle_midi_event_func_t h
|
|||
goto error_recovery;
|
||||
}
|
||||
|
||||
CFStringRef str_input_portname = CFSTR("input");
|
||||
str_input_portname = CFSTR("input");
|
||||
result = MIDIInputPortCreate(client, str_input_portname,
|
||||
fluid_coremidi_callback,
|
||||
(void *)dev, &dev->input_port);
|
||||
|
@ -231,17 +239,17 @@ delete_fluid_coremidi_driver(fluid_midi_driver_t *p)
|
|||
fluid_coremidi_driver_t *dev = (fluid_coremidi_driver_t *) p;
|
||||
fluid_return_if_fail(dev != NULL);
|
||||
|
||||
if(dev->input_port != NULL)
|
||||
if(dev->input_port != invalid_port)
|
||||
{
|
||||
MIDIPortDispose(dev->input_port);
|
||||
}
|
||||
|
||||
if(dev->client != NULL)
|
||||
if(dev->client != invalid_client)
|
||||
{
|
||||
MIDIClientDispose(dev->client);
|
||||
}
|
||||
|
||||
if(dev->endpoint != NULL)
|
||||
if(dev->endpoint != invalid_endpoint)
|
||||
{
|
||||
MIDIEndpointDispose(dev->endpoint);
|
||||
}
|
||||
|
|
|
@ -87,6 +87,17 @@ new_fluid_midishare_midi_driver(fluid_settings_t *settings,
|
|||
fluid_midishare_midi_driver_t *dev;
|
||||
int i;
|
||||
|
||||
FLUID_LOG(FLUID_WARN,
|
||||
"\n\n"
|
||||
"================ MidiShare MIDI driver has been deprecated! =================\n"
|
||||
"You're using the MidiShare driver. This driver is old, unmaintained and believed\n"
|
||||
"to be unused. If you still need it, pls. let us know by posting to our\n"
|
||||
"mailing list at fluid-dev@nongnu.org - otherwise this driver might be removed\n"
|
||||
"in a future release of FluidSynth!\n"
|
||||
"================ MidiShare MIDI driver has been deprecated! =================\n"
|
||||
"\n"
|
||||
);
|
||||
|
||||
/* not much use doing anything */
|
||||
if(handler == NULL)
|
||||
{
|
||||
|
|
|
@ -25,13 +25,9 @@
|
|||
* This file may make use of C++14, because it's required by oboe anyway.
|
||||
*/
|
||||
|
||||
extern "C" {
|
||||
|
||||
#include "fluid_adriver.h"
|
||||
#include "fluid_settings.h"
|
||||
|
||||
} // extern "C"
|
||||
|
||||
#if OBOE_SUPPORT
|
||||
|
||||
#include <oboe/Oboe.h>
|
||||
|
|
|
@ -187,9 +187,18 @@ new_fluid_oss_audio_driver(fluid_settings_t *settings, fluid_synth_t *synth)
|
|||
}
|
||||
}
|
||||
|
||||
if(stat(devname, &devstat) == -1)
|
||||
dev->dspfd = open(devname, O_WRONLY, 0);
|
||||
|
||||
if(dev->dspfd == -1)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Device <%s> does not exists", devname);
|
||||
FLUID_LOG(FLUID_ERR, "Device <%s> could not be opened for writing: %s",
|
||||
devname, g_strerror(errno));
|
||||
goto error_recovery;
|
||||
}
|
||||
|
||||
if(fstat(dev->dspfd, &devstat) == -1)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "fstat failed on device <%s>: %s", devname, g_strerror(errno));
|
||||
goto error_recovery;
|
||||
}
|
||||
|
||||
|
@ -199,15 +208,6 @@ new_fluid_oss_audio_driver(fluid_settings_t *settings, fluid_synth_t *synth)
|
|||
goto error_recovery;
|
||||
}
|
||||
|
||||
dev->dspfd = open(devname, O_WRONLY, 0);
|
||||
|
||||
if(dev->dspfd == -1)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Device <%s> could not be opened for writing: %s",
|
||||
devname, strerror(errno));
|
||||
goto error_recovery;
|
||||
}
|
||||
|
||||
if(fluid_oss_set_queue_size(dev, sample_size, 2, queuesize, period_size) < 0)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Can't set device buffer size");
|
||||
|
@ -333,9 +333,18 @@ new_fluid_oss_audio_driver2(fluid_settings_t *settings, fluid_audio_func_t func,
|
|||
}
|
||||
}
|
||||
|
||||
if(stat(devname, &devstat) == -1)
|
||||
dev->dspfd = open(devname, O_WRONLY, 0);
|
||||
|
||||
if(dev->dspfd == -1)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Device <%s> does not exists", devname);
|
||||
FLUID_LOG(FLUID_ERR, "Device <%s> could not be opened for writing: %s",
|
||||
devname, g_strerror(errno));
|
||||
goto error_recovery;
|
||||
}
|
||||
|
||||
if(fstat(dev->dspfd, &devstat) == -1)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "fstat failed on device <%s>: %s", devname, g_strerror(errno));
|
||||
goto error_recovery;
|
||||
}
|
||||
|
||||
|
@ -345,16 +354,6 @@ new_fluid_oss_audio_driver2(fluid_settings_t *settings, fluid_audio_func_t func,
|
|||
goto error_recovery;
|
||||
}
|
||||
|
||||
dev->dspfd = open(devname, O_WRONLY, 0);
|
||||
|
||||
if(dev->dspfd == -1)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Device <%s> could not be opened for writing: %s",
|
||||
devname, strerror(errno));
|
||||
goto error_recovery;
|
||||
}
|
||||
|
||||
|
||||
if(fluid_oss_set_queue_size(dev, 16, 2, queuesize, period_size) < 0)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Can't set device buffer size");
|
||||
|
@ -404,7 +403,7 @@ new_fluid_oss_audio_driver2(fluid_settings_t *settings, fluid_audio_func_t func,
|
|||
goto error_recovery;
|
||||
}
|
||||
|
||||
/* allocate the buffers. FIXME!!! don't use interleaved samples */
|
||||
/* allocate the buffers. */
|
||||
dev->buffer = FLUID_MALLOC(dev->buffer_byte_size);
|
||||
dev->buffers[0] = FLUID_ARRAY(float, dev->buffer_size);
|
||||
dev->buffers[1] = FLUID_ARRAY(float, dev->buffer_size);
|
||||
|
@ -464,6 +463,8 @@ delete_fluid_oss_audio_driver(fluid_audio_driver_t *p)
|
|||
}
|
||||
|
||||
FLUID_FREE(dev->buffer);
|
||||
FLUID_FREE(dev->buffers[0]);
|
||||
FLUID_FREE(dev->buffers[1]);
|
||||
FLUID_FREE(dev);
|
||||
}
|
||||
|
||||
|
@ -666,7 +667,7 @@ new_fluid_oss_midi_driver(fluid_settings_t *settings,
|
|||
if(fcntl(dev->fd, F_SETFL, O_NONBLOCK) == -1)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Failed to set OSS MIDI device to non-blocking: %s",
|
||||
strerror(errno));
|
||||
g_strerror(errno));
|
||||
goto error_recovery;
|
||||
}
|
||||
|
||||
|
@ -755,7 +756,7 @@ fluid_oss_midi_run(void *d)
|
|||
|
||||
if(n < 0)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Error waiting for MIDI input: %s", strerror(errno));
|
||||
FLUID_LOG(FLUID_ERR, "Error waiting for MIDI input: %s", g_strerror(errno));
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
324
src/drivers/fluid_pipewire.c
Normal file
324
src/drivers/fluid_pipewire.c
Normal file
|
@ -0,0 +1,324 @@
|
|||
/* FluidSynth - A Software Synthesizer
|
||||
*
|
||||
* Copyright (C) 2003 Peter Hanappe and others.
|
||||
* Copyright (C) 2021 E. "sykhro" Melucci
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA
|
||||
*/
|
||||
|
||||
/* fluid_pipewire.c
|
||||
*
|
||||
* Audio driver for PipeWire.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "fluid_synth.h"
|
||||
#include "fluid_adriver.h"
|
||||
#include "fluid_settings.h"
|
||||
|
||||
#if PIPEWIRE_SUPPORT
|
||||
|
||||
#include <pipewire/pipewire.h>
|
||||
#include <spa/param/audio/format-utils.h>
|
||||
|
||||
/* At the moment, only stereo is supported */
|
||||
#define NUM_CHANNELS 2
|
||||
static const int stride = sizeof(float) * NUM_CHANNELS;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
fluid_audio_driver_t driver;
|
||||
fluid_audio_func_t user_callback;
|
||||
void *data;
|
||||
|
||||
/* Used only with the user-provided callback */
|
||||
float *lbuf, *rbuf;
|
||||
|
||||
int buffer_period;
|
||||
struct spa_pod_builder *builder;
|
||||
|
||||
struct pw_thread_loop *pw_loop;
|
||||
struct pw_stream *pw_stream;
|
||||
struct pw_stream_events *events;
|
||||
|
||||
} fluid_pipewire_audio_driver_t;
|
||||
|
||||
|
||||
/* Fast-path rendering routine with no user processing callbacks */
|
||||
static void fluid_pipewire_event_process(void *data)
|
||||
{
|
||||
fluid_pipewire_audio_driver_t *drv = data;
|
||||
struct pw_buffer *pwb;
|
||||
struct spa_buffer *buf;
|
||||
float *dest;
|
||||
|
||||
pwb = pw_stream_dequeue_buffer(drv->pw_stream);
|
||||
|
||||
if(!pwb)
|
||||
{
|
||||
FLUID_LOG(FLUID_WARN, "No buffers!");
|
||||
return;
|
||||
}
|
||||
|
||||
buf = pwb->buffer;
|
||||
dest = buf->datas[0].data;
|
||||
|
||||
if(!dest)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
fluid_synth_write_float(drv->data, drv->buffer_period, dest, 0, 2, dest, 1, 2);
|
||||
buf->datas[0].chunk->offset = 0;
|
||||
buf->datas[0].chunk->stride = stride;
|
||||
buf->datas[0].chunk->size = drv->buffer_period * stride;
|
||||
|
||||
pw_stream_queue_buffer(drv->pw_stream, pwb);
|
||||
}
|
||||
|
||||
/* Rendering routine with support for user-defined audio manipulation */
|
||||
static void fluid_pipewire_event_process2(void *data)
|
||||
{
|
||||
fluid_pipewire_audio_driver_t *drv = data;
|
||||
struct pw_buffer *pwb;
|
||||
struct spa_buffer *buf;
|
||||
float *dest;
|
||||
float *channels[NUM_CHANNELS] = { drv->lbuf, drv->rbuf };
|
||||
int i;
|
||||
|
||||
pwb = pw_stream_dequeue_buffer(drv->pw_stream);
|
||||
|
||||
if(!pwb)
|
||||
{
|
||||
FLUID_LOG(FLUID_WARN, "No buffers!");
|
||||
return;
|
||||
}
|
||||
|
||||
buf = pwb->buffer;
|
||||
dest = buf->datas[0].data;
|
||||
|
||||
if(!dest)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
FLUID_MEMSET(drv->lbuf, 0, drv->buffer_period * sizeof(float));
|
||||
FLUID_MEMSET(drv->rbuf, 0, drv->buffer_period * sizeof(float));
|
||||
|
||||
(*drv->user_callback)(drv->data, drv->buffer_period, 0, NULL, NUM_CHANNELS, channels);
|
||||
|
||||
/* Interleave the floating point data */
|
||||
for(i = 0; i < drv->buffer_period; i++)
|
||||
{
|
||||
dest[i * 2] = drv->lbuf[i];
|
||||
dest[i * 2 + 1] = drv->rbuf[i];
|
||||
}
|
||||
|
||||
buf->datas[0].chunk->offset = 0;
|
||||
buf->datas[0].chunk->stride = stride;
|
||||
buf->datas[0].chunk->size = drv->buffer_period * stride;
|
||||
|
||||
pw_stream_queue_buffer(drv->pw_stream, pwb);
|
||||
}
|
||||
|
||||
fluid_audio_driver_t *new_fluid_pipewire_audio_driver(fluid_settings_t *settings, fluid_synth_t *synth)
|
||||
{
|
||||
return new_fluid_pipewire_audio_driver2(settings, NULL, synth);
|
||||
}
|
||||
|
||||
fluid_audio_driver_t *
|
||||
new_fluid_pipewire_audio_driver2(fluid_settings_t *settings, fluid_audio_func_t func, void *data)
|
||||
{
|
||||
fluid_pipewire_audio_driver_t *drv;
|
||||
int period_size;
|
||||
int buffer_length;
|
||||
int res;
|
||||
int pw_flags;
|
||||
int realtime_prio = 0;
|
||||
double sample_rate;
|
||||
char *media_role = NULL;
|
||||
char *media_type = NULL;
|
||||
char *media_category = NULL;
|
||||
float *buffer = NULL;
|
||||
const struct spa_pod *params[1];
|
||||
|
||||
drv = FLUID_NEW(fluid_pipewire_audio_driver_t);
|
||||
|
||||
if(!drv)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FLUID_MEMSET(drv, 0, sizeof(*drv));
|
||||
|
||||
fluid_settings_getint(settings, "audio.period-size", &period_size);
|
||||
fluid_settings_getint(settings, "audio.realtime-prio", &realtime_prio);
|
||||
fluid_settings_getnum(settings, "synth.sample-rate", &sample_rate);
|
||||
fluid_settings_dupstr(settings, "audio.pipewire.media-role", &media_role);
|
||||
fluid_settings_dupstr(settings, "audio.pipewire.media-type", &media_type);
|
||||
fluid_settings_dupstr(settings, "audio.pipewire.media-category", &media_category);
|
||||
|
||||
drv->data = data;
|
||||
drv->user_callback = func;
|
||||
drv->buffer_period = period_size;
|
||||
|
||||
drv->events = FLUID_NEW(struct pw_stream_events);
|
||||
|
||||
if(!drv->events)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||
goto driver_cleanup;
|
||||
}
|
||||
|
||||
FLUID_MEMSET(drv->events, 0, sizeof(*drv->events));
|
||||
drv->events->version = PW_VERSION_STREAM_EVENTS;
|
||||
drv->events->process = func ? fluid_pipewire_event_process2 : fluid_pipewire_event_process;
|
||||
|
||||
drv->pw_loop = pw_thread_loop_new("fluid_pipewire", NULL);
|
||||
|
||||
if(!drv->pw_loop)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Failed to allocate PipeWire loop. Have you called pw_init() ?");
|
||||
goto driver_cleanup;
|
||||
}
|
||||
|
||||
drv->pw_stream = pw_stream_new_simple(
|
||||
pw_thread_loop_get_loop(drv->pw_loop),
|
||||
"FluidSynth",
|
||||
pw_properties_new(PW_KEY_MEDIA_TYPE, media_type, PW_KEY_MEDIA_CATEGORY, media_category, PW_KEY_MEDIA_ROLE, media_role, NULL),
|
||||
drv->events,
|
||||
drv);
|
||||
|
||||
if(!drv->pw_stream)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Failed to allocate PipeWire stream");
|
||||
goto driver_cleanup;
|
||||
}
|
||||
|
||||
buffer = FLUID_ARRAY(float, NUM_CHANNELS * period_size);
|
||||
|
||||
if(!buffer)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||
goto driver_cleanup;
|
||||
}
|
||||
|
||||
buffer_length = period_size * sizeof(float) * NUM_CHANNELS;
|
||||
|
||||
drv->builder = FLUID_NEW(struct spa_pod_builder);
|
||||
|
||||
if(!drv->builder)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||
goto driver_cleanup;
|
||||
}
|
||||
|
||||
FLUID_MEMSET(drv->builder, 0, sizeof(*drv->builder));
|
||||
drv->builder->data = buffer;
|
||||
drv->builder->size = buffer_length;
|
||||
|
||||
if(func)
|
||||
{
|
||||
drv->lbuf = FLUID_ARRAY(float, period_size);
|
||||
drv->rbuf = FLUID_ARRAY(float, period_size);
|
||||
|
||||
if(!drv->lbuf || !drv->rbuf)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||
goto driver_cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
params[0] = spa_format_audio_raw_build(drv->builder,
|
||||
SPA_PARAM_EnumFormat,
|
||||
&SPA_AUDIO_INFO_RAW_INIT(.format = SPA_AUDIO_FORMAT_F32,
|
||||
.channels = 2,
|
||||
.rate = sample_rate));
|
||||
|
||||
pw_flags = PW_STREAM_FLAG_AUTOCONNECT | PW_STREAM_FLAG_MAP_BUFFERS;
|
||||
pw_flags |= realtime_prio ? PW_STREAM_FLAG_RT_PROCESS : 0;
|
||||
res = pw_stream_connect(drv->pw_stream, PW_DIRECTION_OUTPUT, PW_ID_ANY, pw_flags, params, 1);
|
||||
|
||||
if(res < 0)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "PipeWire stream connection failed");
|
||||
goto driver_cleanup;
|
||||
}
|
||||
|
||||
res = pw_thread_loop_start(drv->pw_loop);
|
||||
|
||||
if(res != 0)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Failed starting PipeWire loop");
|
||||
goto driver_cleanup;
|
||||
}
|
||||
|
||||
FLUID_LOG(FLUID_INFO, "Using PipeWire audio driver");
|
||||
|
||||
FLUID_FREE(media_role);
|
||||
FLUID_FREE(media_type);
|
||||
FLUID_FREE(media_category);
|
||||
|
||||
return (fluid_audio_driver_t *)drv;
|
||||
|
||||
driver_cleanup:
|
||||
FLUID_FREE(media_role);
|
||||
FLUID_FREE(media_type);
|
||||
FLUID_FREE(media_category);
|
||||
|
||||
delete_fluid_pipewire_audio_driver((fluid_audio_driver_t *)drv);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void delete_fluid_pipewire_audio_driver(fluid_audio_driver_t *p)
|
||||
{
|
||||
fluid_pipewire_audio_driver_t *drv = (fluid_pipewire_audio_driver_t *)p;
|
||||
fluid_return_if_fail(drv);
|
||||
|
||||
if(drv->pw_stream)
|
||||
{
|
||||
pw_stream_destroy(drv->pw_stream);
|
||||
}
|
||||
|
||||
if(drv->pw_loop)
|
||||
{
|
||||
pw_thread_loop_destroy(drv->pw_loop);
|
||||
}
|
||||
|
||||
FLUID_FREE(drv->lbuf);
|
||||
FLUID_FREE(drv->rbuf);
|
||||
|
||||
if(drv->builder)
|
||||
{
|
||||
FLUID_FREE(drv->builder->data);
|
||||
}
|
||||
|
||||
FLUID_FREE(drv->builder);
|
||||
|
||||
FLUID_FREE(drv->events);
|
||||
|
||||
FLUID_FREE(drv);
|
||||
}
|
||||
|
||||
void fluid_pipewire_audio_driver_settings(fluid_settings_t *settings)
|
||||
{
|
||||
fluid_settings_register_str(settings, "audio.pipewire.media-role", "Music", 0);
|
||||
fluid_settings_register_str(settings, "audio.pipewire.media-type", "Audio", 0);
|
||||
fluid_settings_register_str(settings, "audio.pipewire.media-category", "Playback", 0);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -83,12 +83,12 @@ new_fluid_pulse_audio_driver2(fluid_settings_t *settings,
|
|||
pa_sample_spec samplespec;
|
||||
pa_buffer_attr bufattr;
|
||||
double sample_rate;
|
||||
int period_size, period_bytes, adjust_latency;
|
||||
int period_size, period_bytes, adjust_latency, periods;
|
||||
char *server = NULL;
|
||||
char *device = NULL;
|
||||
char *media_role = NULL;
|
||||
int realtime_prio = 0;
|
||||
int err;
|
||||
int err = 0;
|
||||
float *left = NULL,
|
||||
*right = NULL,
|
||||
*buf = NULL;
|
||||
|
@ -103,6 +103,7 @@ new_fluid_pulse_audio_driver2(fluid_settings_t *settings,
|
|||
|
||||
FLUID_MEMSET(dev, 0, sizeof(fluid_pulse_audio_driver_t));
|
||||
|
||||
fluid_settings_getint(settings, "audio.periods", &periods);
|
||||
fluid_settings_getint(settings, "audio.period-size", &period_size);
|
||||
fluid_settings_getnum(settings, "synth.sample-rate", &sample_rate);
|
||||
fluid_settings_dupstr(settings, "audio.pulseaudio.server", &server); /* ++ alloc server string */
|
||||
|
@ -143,7 +144,7 @@ new_fluid_pulse_audio_driver2(fluid_settings_t *settings,
|
|||
samplespec.rate = sample_rate;
|
||||
|
||||
period_bytes = period_size * sizeof(float) * 2;
|
||||
bufattr.maxlength = adjust_latency ? -1 : period_bytes;
|
||||
bufattr.maxlength = adjust_latency ? -1 : period_bytes * periods;
|
||||
bufattr.tlength = period_bytes;
|
||||
bufattr.minreq = -1;
|
||||
bufattr.prebuf = -1; /* Just initialize to same value as tlength */
|
||||
|
@ -155,9 +156,9 @@ new_fluid_pulse_audio_driver2(fluid_settings_t *settings,
|
|||
&bufattr,
|
||||
&err);
|
||||
|
||||
if(!dev->pa_handle)
|
||||
if(!dev->pa_handle || err != PA_OK)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Failed to create PulseAudio connection");
|
||||
FLUID_LOG(FLUID_ERR, "Failed to create PulseAudio connection, because pa_simple_new() failed with error: %s", pa_strerror(err));
|
||||
goto error_recovery;
|
||||
}
|
||||
|
||||
|
@ -176,6 +177,7 @@ new_fluid_pulse_audio_driver2(fluid_settings_t *settings,
|
|||
}
|
||||
|
||||
buf = FLUID_ARRAY(float, period_size * 2);
|
||||
|
||||
if(buf == NULL)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Out of memory.");
|
||||
|
@ -242,10 +244,8 @@ fluid_pulse_audio_run(void *d)
|
|||
{
|
||||
fluid_pulse_audio_driver_t *dev = (fluid_pulse_audio_driver_t *) d;
|
||||
float *buf = dev->buf;
|
||||
int buffer_size;
|
||||
int err;
|
||||
|
||||
buffer_size = dev->buffer_size;
|
||||
int buffer_size = dev->buffer_size;
|
||||
int err = 0;
|
||||
|
||||
while(dev->cont)
|
||||
{
|
||||
|
@ -254,9 +254,20 @@ fluid_pulse_audio_run(void *d)
|
|||
if(pa_simple_write(dev->pa_handle, buf,
|
||||
buffer_size * sizeof(float) * 2, &err) < 0)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Error writing to PulseAudio connection.");
|
||||
FLUID_LOG(FLUID_ERR, "Error writing to PulseAudio connection: %s", pa_strerror(err));
|
||||
break;
|
||||
}
|
||||
|
||||
#if 0
|
||||
{
|
||||
pa_usec_t pa_latency = pa_simple_get_latency(dev->pa_handle, &err);
|
||||
|
||||
if(err == PA_OK)
|
||||
{
|
||||
FLUID_LOG(FLUID_DBG, "PulseAudio latency: %d ms", (int) pa_latency / 1000);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} /* while (dev->cont) */
|
||||
|
||||
return FLUID_THREAD_RETURN_VALUE;
|
||||
|
@ -271,12 +282,10 @@ fluid_pulse_audio_run2(void *d)
|
|||
*right = dev->right,
|
||||
*buf = dev->buf;
|
||||
float *handle[2];
|
||||
int buffer_size;
|
||||
int err;
|
||||
int buffer_size = dev->buffer_size;
|
||||
int err = 0;
|
||||
int i;
|
||||
|
||||
buffer_size = dev->buffer_size;
|
||||
|
||||
handle[0] = left;
|
||||
handle[1] = right;
|
||||
|
||||
|
@ -297,9 +306,20 @@ fluid_pulse_audio_run2(void *d)
|
|||
if(pa_simple_write(dev->pa_handle, buf,
|
||||
buffer_size * sizeof(float) * 2, &err) < 0)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Error writing to PulseAudio connection.");
|
||||
FLUID_LOG(FLUID_ERR, "Error writing to PulseAudio connection: %s", pa_strerror(err));
|
||||
break;
|
||||
}
|
||||
|
||||
#if 0
|
||||
{
|
||||
pa_usec_t pa_latency = pa_simple_get_latency(dev->pa_handle, &err);
|
||||
|
||||
if(err == PA_OK)
|
||||
{
|
||||
FLUID_LOG(FLUID_DBG, "PulseAudio latency: %d ms", (int) pa_latency / 1000);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} /* while (dev->cont) */
|
||||
|
||||
return FLUID_THREAD_RETURN_VALUE;
|
||||
|
|
|
@ -803,6 +803,7 @@ static void fluid_wasapi_finddev_callback(IMMDevice *dev, void *data)
|
|||
{
|
||||
fluid_wasapi_finddev_data_t *d = (fluid_wasapi_finddev_data_t *)data;
|
||||
int nsz;
|
||||
size_t id_len;
|
||||
char *name = NULL;
|
||||
wchar_t *id = NULL;
|
||||
IPropertyStore *prop = NULL;
|
||||
|
@ -841,9 +842,15 @@ static void fluid_wasapi_finddev_callback(IMMDevice *dev, void *data)
|
|||
goto cleanup;
|
||||
}
|
||||
|
||||
nsz = wcslen(id);
|
||||
d->id = FLUID_ARRAY(wchar_t, nsz + 1);
|
||||
FLUID_MEMCPY(d->id, id, sizeof(wchar_t) * (nsz + 1));
|
||||
id_len = wcslen(id);
|
||||
if(id_len >= UINT_MAX / sizeof(wchar_t))
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "wasapi: the returned device identifier was way too long");
|
||||
goto cleanup;
|
||||
}
|
||||
id_len++;
|
||||
d->id = FLUID_ARRAY(wchar_t, id_len);
|
||||
FLUID_MEMCPY(d->id, id, sizeof(wchar_t) * id_len);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
|
|
|
@ -145,21 +145,28 @@ fluid_winmidi_callback(HMIDIIN hmi, UINT wMsg, DWORD_PTR dwInstance,
|
|||
break;
|
||||
|
||||
case MIM_DATA:
|
||||
event.type = msg_type(msg_param);
|
||||
event.channel = msg_chan(msg_param) + dev_infos->channel_map;
|
||||
|
||||
FLUID_LOG(FLUID_DBG, "\ndevice at index %d sending MIDI message on channel %d, forwarded on channel: %d",
|
||||
dev_infos->dev_idx, msg_chan(msg_param), event.channel);
|
||||
|
||||
if(event.type != PITCH_BEND)
|
||||
if(msg_param < 0xF0) /* Voice category message */
|
||||
{
|
||||
event.param1 = msg_p1(msg_param);
|
||||
event.param2 = msg_p2(msg_param);
|
||||
event.type = msg_type(msg_param);
|
||||
event.channel = msg_chan(msg_param) + dev_infos->channel_map;
|
||||
|
||||
FLUID_LOG(FLUID_DBG, "\ndevice at index %d sending MIDI message on channel %d, forwarded on channel: %d",
|
||||
dev_infos->dev_idx, msg_chan(msg_param), event.channel);
|
||||
|
||||
if(event.type != PITCH_BEND)
|
||||
{
|
||||
event.param1 = msg_p1(msg_param);
|
||||
event.param2 = msg_p2(msg_param);
|
||||
}
|
||||
else /* Pitch bend is a 14 bit value */
|
||||
{
|
||||
event.param1 = (msg_p2(msg_param) << 7) | msg_p1(msg_param);
|
||||
event.param2 = 0;
|
||||
}
|
||||
}
|
||||
else /* Pitch bend is a 14 bit value */
|
||||
else /* System message */
|
||||
{
|
||||
event.param1 = (msg_p2(msg_param) << 7) | msg_p1(msg_param);
|
||||
event.param2 = 0;
|
||||
event.type = msg_param;
|
||||
}
|
||||
|
||||
(*dev->driver.handler)(dev->driver.data, &event);
|
||||
|
|
|
@ -42,6 +42,10 @@
|
|||
#include <SDL.h>
|
||||
#endif
|
||||
|
||||
#if PIPEWIRE_SUPPORT
|
||||
#include <pipewire/pipewire.h>
|
||||
#endif
|
||||
|
||||
void print_usage(void);
|
||||
void print_help(fluid_settings_t *settings);
|
||||
void print_welcome(void);
|
||||
|
@ -400,7 +404,8 @@ int main(int argc, char **argv)
|
|||
#endif
|
||||
|
||||
#if SDL2_SUPPORT
|
||||
|
||||
// Tell SDL that it shouldn't intercept signals, otherwise SIGINT and SIGTERM won't quit fluidsynth
|
||||
SDL_SetHint(SDL_HINT_NO_SIGNAL_HANDLERS, "1");
|
||||
if(SDL_Init(SDL_INIT_AUDIO) != 0)
|
||||
{
|
||||
fprintf(stderr, "Warning: Unable to initialize SDL2 Audio: %s", SDL_GetError());
|
||||
|
@ -409,7 +414,11 @@ int main(int argc, char **argv)
|
|||
{
|
||||
atexit(SDL_Quit);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if PIPEWIRE_SUPPORT
|
||||
pw_init(&argc, &argv);
|
||||
atexit(pw_deinit);
|
||||
#endif
|
||||
|
||||
/* create the settings */
|
||||
|
@ -890,13 +899,13 @@ int main(int argc, char **argv)
|
|||
if(config_file == NULL)
|
||||
{
|
||||
config_file = fluid_get_userconf(buf, sizeof(buf));
|
||||
if(config_file == NULL)
|
||||
if(config_file == NULL || !g_file_test(config_file, G_FILE_TEST_EXISTS))
|
||||
{
|
||||
config_file = fluid_get_sysconf(buf, sizeof(buf));
|
||||
}
|
||||
|
||||
/* if the automatically selected command file does not exist, do not even attempt to open it */
|
||||
if(!g_file_test(config_file, G_FILE_TEST_EXISTS))
|
||||
if(config_file != NULL && !fluid_file_test(config_file, FLUID_FILE_TEST_EXISTS))
|
||||
{
|
||||
config_file = NULL;
|
||||
}
|
||||
|
@ -1213,7 +1222,7 @@ void
|
|||
print_welcome()
|
||||
{
|
||||
printf("FluidSynth runtime version %s\n"
|
||||
"Copyright (C) 2000-2021 Peter Hanappe and others.\n"
|
||||
"Copyright (C) 2000-2022 Peter Hanappe and others.\n"
|
||||
"Distributed under the LGPL license.\n"
|
||||
"SoundFont(R) is a registered trademark of Creative Technology Ltd.\n\n",
|
||||
fluid_version_str());
|
||||
|
|
|
@ -21,14 +21,14 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
|||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR})
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR})
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../)
|
||||
|
||||
# Add the executable that generates the table
|
||||
add_executable( make_tables
|
||||
make_tables.c
|
||||
gen_conv.c
|
||||
gen_rvoice_dsp.c)
|
||||
|
||||
target_include_directories( make_tables PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../ )
|
||||
|
||||
if ( WIN32 )
|
||||
add_definitions ( -D_USE_MATH_DEFINES -D_CRT_SECURE_NO_WARNINGS )
|
||||
else ( WIN32 )
|
||||
|
|
|
@ -126,8 +126,13 @@ new_fluid_midi_file(const char *buffer, size_t length)
|
|||
{
|
||||
fluid_midi_file *mf;
|
||||
|
||||
mf = FLUID_NEW(fluid_midi_file);
|
||||
if(length > INT_MAX)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Refusing to open a MIDI file which is bigger than 2GiB");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mf = FLUID_NEW(fluid_midi_file);
|
||||
if(mf == NULL)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||
|
@ -140,7 +145,7 @@ new_fluid_midi_file(const char *buffer, size_t length)
|
|||
mf->running_status = -1;
|
||||
|
||||
mf->buffer = buffer;
|
||||
mf->buf_len = length;
|
||||
mf->buf_len = (int)length;
|
||||
mf->buf_pos = 0;
|
||||
mf->eof = FALSE;
|
||||
|
||||
|
@ -488,7 +493,7 @@ fluid_midi_file_read_track(fluid_midi_file *mf, fluid_player_t *player, int num)
|
|||
if(fluid_isasciistring((char *) id) == 0)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR,
|
||||
"An non-ascii track header found, corrupt file");
|
||||
"A non-ascii track header found, corrupt file");
|
||||
return FLUID_FAILED;
|
||||
|
||||
}
|
||||
|
@ -1106,7 +1111,7 @@ delete_fluid_midi_event(fluid_midi_event_t *evt)
|
|||
* @return Event type field (MIDI status byte without channel)
|
||||
*/
|
||||
int
|
||||
fluid_midi_event_get_type(fluid_midi_event_t *evt)
|
||||
fluid_midi_event_get_type(const fluid_midi_event_t *evt)
|
||||
{
|
||||
return evt->type;
|
||||
}
|
||||
|
@ -1130,7 +1135,7 @@ fluid_midi_event_set_type(fluid_midi_event_t *evt, int type)
|
|||
* @return Channel field
|
||||
*/
|
||||
int
|
||||
fluid_midi_event_get_channel(fluid_midi_event_t *evt)
|
||||
fluid_midi_event_get_channel(const fluid_midi_event_t *evt)
|
||||
{
|
||||
return evt->channel;
|
||||
}
|
||||
|
@ -1154,7 +1159,7 @@ fluid_midi_event_set_channel(fluid_midi_event_t *evt, int chan)
|
|||
* @return MIDI note number (0-127)
|
||||
*/
|
||||
int
|
||||
fluid_midi_event_get_key(fluid_midi_event_t *evt)
|
||||
fluid_midi_event_get_key(const fluid_midi_event_t *evt)
|
||||
{
|
||||
return evt->param1;
|
||||
}
|
||||
|
@ -1178,7 +1183,7 @@ fluid_midi_event_set_key(fluid_midi_event_t *evt, int v)
|
|||
* @return MIDI velocity number (0-127)
|
||||
*/
|
||||
int
|
||||
fluid_midi_event_get_velocity(fluid_midi_event_t *evt)
|
||||
fluid_midi_event_get_velocity(const fluid_midi_event_t *evt)
|
||||
{
|
||||
return evt->param2;
|
||||
}
|
||||
|
@ -1202,7 +1207,7 @@ fluid_midi_event_set_velocity(fluid_midi_event_t *evt, int v)
|
|||
* @return MIDI control number
|
||||
*/
|
||||
int
|
||||
fluid_midi_event_get_control(fluid_midi_event_t *evt)
|
||||
fluid_midi_event_get_control(const fluid_midi_event_t *evt)
|
||||
{
|
||||
return evt->param1;
|
||||
}
|
||||
|
@ -1226,7 +1231,7 @@ fluid_midi_event_set_control(fluid_midi_event_t *evt, int v)
|
|||
* @return Value field
|
||||
*/
|
||||
int
|
||||
fluid_midi_event_get_value(fluid_midi_event_t *evt)
|
||||
fluid_midi_event_get_value(const fluid_midi_event_t *evt)
|
||||
{
|
||||
return evt->param2;
|
||||
}
|
||||
|
@ -1250,7 +1255,7 @@ fluid_midi_event_set_value(fluid_midi_event_t *evt, int v)
|
|||
* @return MIDI program number (0-127)
|
||||
*/
|
||||
int
|
||||
fluid_midi_event_get_program(fluid_midi_event_t *evt)
|
||||
fluid_midi_event_get_program(const fluid_midi_event_t *evt)
|
||||
{
|
||||
return evt->param1;
|
||||
}
|
||||
|
@ -1274,7 +1279,7 @@ fluid_midi_event_set_program(fluid_midi_event_t *evt, int val)
|
|||
* @return Pitch value (14 bit value, 0-16383, 8192 is center)
|
||||
*/
|
||||
int
|
||||
fluid_midi_event_get_pitch(fluid_midi_event_t *evt)
|
||||
fluid_midi_event_get_pitch(const fluid_midi_event_t *evt)
|
||||
{
|
||||
return evt->param1;
|
||||
}
|
||||
|
@ -2331,6 +2336,12 @@ static void fluid_player_update_tempo(fluid_player_t *player)
|
|||
int tempo; /* tempo in micro seconds by quarter note */
|
||||
float deltatime;
|
||||
|
||||
/* do nothing if the division is still unknown to avoid a div by zero */
|
||||
if(player->division == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(fluid_atomic_int_get(&player->sync_mode))
|
||||
{
|
||||
/* take internal tempo from MIDI file */
|
||||
|
@ -2395,6 +2406,10 @@ static void fluid_player_update_tempo(fluid_player_t *player)
|
|||
* #FLUID_PLAYER_TEMPO_INTERNAL will set the player to follow this internal
|
||||
* tempo.
|
||||
*
|
||||
* @warning If the function is called when no MIDI file is loaded or currently playing, it
|
||||
* would have caused a division by zero in fluidsynth 2.2.7 and earlier. Starting with 2.2.8, the
|
||||
* new tempo change will be stashed and applied later.
|
||||
*
|
||||
* @return #FLUID_OK if success or #FLUID_FAILED otherwise (incorrect parameters).
|
||||
* @since 2.2.0
|
||||
*/
|
||||
|
@ -2637,14 +2652,9 @@ fluid_midi_parser_parse(fluid_midi_parser_t *parser, unsigned char c)
|
|||
* of another message. */
|
||||
if(c >= 0xF8)
|
||||
{
|
||||
if(c == MIDI_SYSTEM_RESET)
|
||||
{
|
||||
parser->event.type = c;
|
||||
parser->status = 0; /* clear the status */
|
||||
return &parser->event;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
parser->event.type = c;
|
||||
parser->status = 0; /* clear the status */
|
||||
return &parser->event;
|
||||
}
|
||||
|
||||
/* Status byte? - If previous message not yet complete, it is discarded (re-sync). */
|
||||
|
|
|
@ -367,64 +367,20 @@ static fluid_seq_id_t get_fluidsynth_dest(fluid_sequencer_t *seq)
|
|||
*
|
||||
* @since 1.1.0
|
||||
*/
|
||||
int
|
||||
fluid_sequencer_add_midi_event_to_buffer(void *data, fluid_midi_event_t *event)
|
||||
int fluid_sequencer_add_midi_event_to_buffer(void *data, fluid_midi_event_t *event)
|
||||
{
|
||||
fluid_event_t evt;
|
||||
fluid_sequencer_t *seq;
|
||||
int chan;
|
||||
|
||||
fluid_return_val_if_fail(data != NULL, FLUID_FAILED);
|
||||
fluid_return_val_if_fail(event != NULL, FLUID_FAILED);
|
||||
|
||||
seq = (fluid_sequencer_t *) data;
|
||||
chan = fluid_midi_event_get_channel(event);
|
||||
seq = (fluid_sequencer_t *)data;
|
||||
|
||||
fluid_event_clear(&evt);
|
||||
fluid_event_from_midi_event(&evt, event);
|
||||
fluid_event_set_dest(&evt, get_fluidsynth_dest(seq));
|
||||
|
||||
switch(fluid_midi_event_get_type(event))
|
||||
{
|
||||
case NOTE_OFF:
|
||||
fluid_event_noteoff(&evt, chan, (short)fluid_midi_event_get_key(event));
|
||||
break;
|
||||
|
||||
case NOTE_ON:
|
||||
fluid_event_noteon(&evt, fluid_midi_event_get_channel(event),
|
||||
(short)fluid_midi_event_get_key(event), (short)fluid_midi_event_get_velocity(event));
|
||||
break;
|
||||
|
||||
case CONTROL_CHANGE:
|
||||
fluid_event_control_change(&evt, chan, (short)fluid_midi_event_get_control(event),
|
||||
(short)fluid_midi_event_get_value(event));
|
||||
break;
|
||||
|
||||
case PROGRAM_CHANGE:
|
||||
fluid_event_program_change(&evt, chan, (short)fluid_midi_event_get_program(event));
|
||||
break;
|
||||
|
||||
case PITCH_BEND:
|
||||
fluid_event_pitch_bend(&evt, chan, fluid_midi_event_get_pitch(event));
|
||||
break;
|
||||
|
||||
case CHANNEL_PRESSURE:
|
||||
fluid_event_channel_pressure(&evt, chan, (short)fluid_midi_event_get_program(event));
|
||||
break;
|
||||
|
||||
case KEY_PRESSURE:
|
||||
fluid_event_key_pressure(&evt, chan,
|
||||
(short)fluid_midi_event_get_key(event),
|
||||
(short)fluid_midi_event_get_value(event));
|
||||
break;
|
||||
|
||||
case MIDI_SYSTEM_RESET:
|
||||
fluid_event_system_reset(&evt);
|
||||
break;
|
||||
|
||||
default: /* Not yet implemented */
|
||||
return FLUID_FAILED;
|
||||
}
|
||||
|
||||
/* Schedule for sending at next call to fluid_sequencer_process */
|
||||
return fluid_sequencer_send_at(seq, &evt, 0, 0);
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ struct _fluid_env_data_t
|
|||
};
|
||||
|
||||
/* Indices for envelope tables */
|
||||
enum fluid_voice_envelope_index_t
|
||||
enum fluid_voice_envelope_index
|
||||
{
|
||||
FLUID_VOICE_ENVDELAY,
|
||||
FLUID_VOICE_ENVATTACK,
|
||||
|
@ -49,7 +49,7 @@ enum fluid_voice_envelope_index_t
|
|||
FLUID_VOICE_ENVLAST
|
||||
};
|
||||
|
||||
typedef enum fluid_voice_envelope_index_t fluid_adsr_env_section_t;
|
||||
typedef enum fluid_voice_envelope_index fluid_adsr_env_section_t;
|
||||
|
||||
typedef struct _fluid_adsr_env_t fluid_adsr_env_t;
|
||||
|
||||
|
@ -57,14 +57,14 @@ struct _fluid_adsr_env_t
|
|||
{
|
||||
fluid_env_data_t data[FLUID_VOICE_ENVLAST];
|
||||
unsigned int count;
|
||||
int section;
|
||||
fluid_real_t val; /* the current value of the envelope */
|
||||
fluid_adsr_env_section_t section;
|
||||
};
|
||||
|
||||
/* For performance, all functions are inlined */
|
||||
|
||||
static FLUID_INLINE void
|
||||
fluid_adsr_env_calc(fluid_adsr_env_t *env, int is_volenv)
|
||||
fluid_adsr_env_calc(fluid_adsr_env_t *env)
|
||||
{
|
||||
fluid_env_data_t *env_data;
|
||||
fluid_real_t x;
|
||||
|
@ -76,7 +76,8 @@ fluid_adsr_env_calc(fluid_adsr_env_t *env, int is_volenv)
|
|||
{
|
||||
// If we're switching envelope stages from decay to sustain, force the value to be the end value of the previous stage
|
||||
// Hmm, should this only apply to volenv? It was so before refactoring, so keep it for now. [DH]
|
||||
if(env->section == FLUID_VOICE_ENVDECAY && is_volenv)
|
||||
// No, must apply to both, otherwise some voices may sound detuned. [TM] (https://github.com/FluidSynth/fluidsynth/issues/1059)
|
||||
if(env->section == FLUID_VOICE_ENVDECAY)
|
||||
{
|
||||
env->val = env_data->min * env_data->coeff;
|
||||
}
|
||||
|
@ -106,8 +107,6 @@ fluid_adsr_env_calc(fluid_adsr_env_t *env, int is_volenv)
|
|||
}
|
||||
|
||||
env->val = x;
|
||||
|
||||
|
||||
}
|
||||
|
||||
/* This one cannot be inlined since it is referenced in
|
||||
|
@ -118,7 +117,7 @@ static FLUID_INLINE void
|
|||
fluid_adsr_env_reset(fluid_adsr_env_t *env)
|
||||
{
|
||||
env->count = 0;
|
||||
env->section = 0;
|
||||
env->section = FLUID_VOICE_ENVDELAY;
|
||||
env->val = 0.0f;
|
||||
}
|
||||
|
||||
|
|
|
@ -331,7 +331,7 @@ fluid_rvoice_write(fluid_rvoice_t *voice, fluid_real_t *dsp_buf)
|
|||
|
||||
/******************* vol env **********************/
|
||||
|
||||
fluid_adsr_env_calc(&voice->envlfo.volenv, 1);
|
||||
fluid_adsr_env_calc(&voice->envlfo.volenv);
|
||||
fluid_check_fpe("voice_write vol env");
|
||||
|
||||
if(fluid_adsr_env_get_section(&voice->envlfo.volenv) == FLUID_VOICE_ENVFINISHED)
|
||||
|
@ -341,7 +341,7 @@ fluid_rvoice_write(fluid_rvoice_t *voice, fluid_real_t *dsp_buf)
|
|||
|
||||
/******************* mod env **********************/
|
||||
|
||||
fluid_adsr_env_calc(&voice->envlfo.modenv, 0);
|
||||
fluid_adsr_env_calc(&voice->envlfo.modenv);
|
||||
fluid_check_fpe("voice_write mod env");
|
||||
|
||||
/******************* lfo **********************/
|
||||
|
|
|
@ -150,6 +150,17 @@ fluid_rvoice_mixer_process_fx(fluid_rvoice_mixer_t *mixer, int current_blockcoun
|
|||
|
||||
fluid_profile_ref_var(prof_ref);
|
||||
|
||||
#ifdef LADSPA
|
||||
|
||||
/* Run the signal through the LADSPA Fx unit. The buffers have already been
|
||||
* set up in fluid_rvoice_mixer_set_ladspa. */
|
||||
if(mixer->ladspa_fx)
|
||||
{
|
||||
fluid_ladspa_run(mixer->ladspa_fx, current_blockcount, FLUID_BUFSIZE);
|
||||
fluid_check_fpe("LADSPA");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if(mix_fx_to_out)
|
||||
{
|
||||
|
@ -238,17 +249,6 @@ fluid_rvoice_mixer_process_fx(fluid_rvoice_mixer_t *mixer, int current_blockcoun
|
|||
current_blockcount * FLUID_BUFSIZE);
|
||||
}
|
||||
|
||||
#ifdef LADSPA
|
||||
|
||||
/* Run the signal through the LADSPA Fx unit. The buffers have already been
|
||||
* set up in fluid_rvoice_mixer_set_ladspa. */
|
||||
if(mixer->ladspa_fx)
|
||||
{
|
||||
fluid_ladspa_run(mixer->ladspa_fx, current_blockcount, FLUID_BUFSIZE);
|
||||
fluid_check_fpe("LADSPA");
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -376,6 +376,7 @@ int fluid_defsfont_load_all_sampledata(fluid_defsfont_t *defsfont, SFData *sfdat
|
|||
fluid_sample_t *sample;
|
||||
int sf3_file = (sfdata->version.major == 3);
|
||||
int sample_parsing_result = FLUID_OK;
|
||||
int invalid_loops_were_sanitized = FALSE;
|
||||
|
||||
/* For SF2 files, we load the sample data in one large block */
|
||||
if(!sf3_file)
|
||||
|
@ -404,7 +405,7 @@ int fluid_defsfont_load_all_sampledata(fluid_defsfont_t *defsfont, SFData *sfdat
|
|||
{
|
||||
/* SF3 samples get loaded individually, as most (or all) of them are in Ogg Vorbis format
|
||||
* anyway */
|
||||
#pragma omp task firstprivate(sample,sfdata,defsfont) shared(sample_parsing_result) default(none)
|
||||
#pragma omp task firstprivate(sample,sfdata,defsfont) shared(sample_parsing_result, invalid_loops_were_sanitized) default(none)
|
||||
{
|
||||
if(fluid_defsfont_load_sampledata(defsfont, sfdata, sample) == FLUID_FAILED)
|
||||
{
|
||||
|
@ -416,24 +417,46 @@ int fluid_defsfont_load_all_sampledata(fluid_defsfont_t *defsfont, SFData *sfdat
|
|||
}
|
||||
else
|
||||
{
|
||||
fluid_sample_sanitize_loop(sample, (sample->end + 1) * sizeof(short));
|
||||
int modified = fluid_sample_sanitize_loop(sample, (sample->end + 1) * sizeof(short));
|
||||
if(modified)
|
||||
{
|
||||
#pragma omp critical
|
||||
{
|
||||
invalid_loops_were_sanitized = TRUE;
|
||||
}
|
||||
}
|
||||
fluid_voice_optimize_sample(sample);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#pragma omp task firstprivate(sample, defsfont) default(none)
|
||||
#pragma omp task firstprivate(sample, defsfont) shared(invalid_loops_were_sanitized) default(none)
|
||||
{
|
||||
int modified;
|
||||
/* Data pointers of SF2 samples point to large sample data block loaded above */
|
||||
sample->data = defsfont->sampledata;
|
||||
sample->data24 = defsfont->sample24data;
|
||||
fluid_sample_sanitize_loop(sample, defsfont->samplesize);
|
||||
modified = fluid_sample_sanitize_loop(sample, defsfont->samplesize);
|
||||
if(modified)
|
||||
{
|
||||
#pragma omp critical
|
||||
{
|
||||
invalid_loops_were_sanitized = TRUE;
|
||||
}
|
||||
}
|
||||
fluid_voice_optimize_sample(sample);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(invalid_loops_were_sanitized)
|
||||
{
|
||||
FLUID_LOG(FLUID_WARN,
|
||||
"Some invalid sample loops were sanitized! If you experience audible glitches, "
|
||||
"start fluidsynth in verbose mode for detailed information.");
|
||||
}
|
||||
|
||||
return sample_parsing_result;
|
||||
}
|
||||
|
||||
|
|
|
@ -789,12 +789,19 @@ int fluid_sample_sanitize_loop(fluid_sample_t *sample, unsigned int buffer_size)
|
|||
if(sample->loopstart == sample->loopend)
|
||||
{
|
||||
/* Some SoundFonts disable loops by setting loopstart = loopend. While
|
||||
* technically invalid, we decided to accept those samples anyway. Just
|
||||
* ensure that those two pointers are within the sampledata by setting
|
||||
* them to 0. Don't report the modification, as this change has no audible
|
||||
* effect. */
|
||||
sample->loopstart = sample->loopend = 0;
|
||||
return FALSE;
|
||||
* technically invalid, we decided to accept those samples anyway.
|
||||
* Before fluidsynth 2.2.5 we've set those indices to zero, as this
|
||||
* change was believed to be inaudible. This turned out to be an
|
||||
* incorrect assumption, as the loop points may still be modified by
|
||||
* loop offset modulators afterwards.
|
||||
*/
|
||||
if(sample->loopstart != sample->start)
|
||||
{
|
||||
// Many soundfonts set loopstart == loopend == sample->start to disabled to loop.
|
||||
// Only report cases where it's not equal to the sample->start, to avoid spam.
|
||||
FLUID_LOG(FLUID_DBG, "Sample '%s': zero length loop detected: loopstart == loopend == '%d', sample start '%d', using it anyway",
|
||||
sample->name, sample->loopstart, sample->start);
|
||||
}
|
||||
}
|
||||
else if(sample->loopstart > sample->loopend)
|
||||
{
|
||||
|
|
|
@ -162,9 +162,10 @@ fluid_channel_init_ctrl(fluid_channel_t *chan, int is_all_ctrl_off)
|
|||
fluid_channel_set_cc(chan, i, 0);
|
||||
}
|
||||
|
||||
fluid_channel_clear_portamento(chan); /* Clear PTC receive */
|
||||
chan->previous_cc_breath = 0;/* Reset previous breath */
|
||||
}
|
||||
/* Unconditionally clear PTC receive (issue #1050) */
|
||||
fluid_channel_clear_portamento(chan);
|
||||
|
||||
/* Reset polyphonic key pressure on all voices */
|
||||
for(i = 0; i < 128; i++)
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
#include "fluid_event.h"
|
||||
#include "fluidsynth_priv.h"
|
||||
#include "fluid_midi.h"
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
|
@ -577,7 +578,88 @@ fluid_event_system_reset(fluid_event_t *evt)
|
|||
evt->type = FLUID_SEQ_SYSTEMRESET;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms an incoming MIDI event (from a MIDI driver or MIDI router) to a
|
||||
* sequencer event.
|
||||
*
|
||||
* @param evt Sequencer event structure
|
||||
* @param event MIDI event
|
||||
* @return #FLUID_OK or #FLUID_FAILED
|
||||
*
|
||||
* @note This function copies the fields of the MIDI event into the provided
|
||||
* sequencer event. Calling applications must create the sequencer event and set
|
||||
* additional fields such as the source and destination of the sequencer event.
|
||||
*
|
||||
* @code{.cpp}
|
||||
* // ... get MIDI event, e.g. using player_callback()
|
||||
*
|
||||
* // Send MIDI event to sequencer to play
|
||||
* fluid_event_t *evt = new_fluid_event();
|
||||
* fluid_event_set_source(evt, -1);
|
||||
* fluid_event_set_dest(evt, seqid);
|
||||
* fluid_event_from_midi_event(evt, event);
|
||||
* fluid_sequencer_send_at(sequencer, evt, 50, 0); // relative time
|
||||
* delete_fluid_event(evt);
|
||||
* @endcode
|
||||
*
|
||||
* @since 2.2.7
|
||||
*/
|
||||
int fluid_event_from_midi_event(fluid_event_t *evt, const fluid_midi_event_t *event)
|
||||
{
|
||||
int chan;
|
||||
fluid_return_val_if_fail(event != NULL, FLUID_FAILED);
|
||||
|
||||
chan = fluid_midi_event_get_channel(event);
|
||||
|
||||
switch (fluid_midi_event_get_type(event))
|
||||
{
|
||||
case NOTE_OFF:
|
||||
fluid_event_noteoff(evt, chan, (short)fluid_midi_event_get_key(event));
|
||||
break;
|
||||
|
||||
case NOTE_ON:
|
||||
fluid_event_noteon(evt,
|
||||
fluid_midi_event_get_channel(event),
|
||||
(short)fluid_midi_event_get_key(event),
|
||||
(short)fluid_midi_event_get_velocity(event));
|
||||
break;
|
||||
|
||||
case CONTROL_CHANGE:
|
||||
fluid_event_control_change(evt,
|
||||
chan,
|
||||
(short)fluid_midi_event_get_control(event),
|
||||
(short)fluid_midi_event_get_value(event));
|
||||
break;
|
||||
|
||||
case PROGRAM_CHANGE:
|
||||
fluid_event_program_change(evt, chan, (short)fluid_midi_event_get_program(event));
|
||||
break;
|
||||
|
||||
case PITCH_BEND:
|
||||
fluid_event_pitch_bend(evt, chan, fluid_midi_event_get_pitch(event));
|
||||
break;
|
||||
|
||||
case CHANNEL_PRESSURE:
|
||||
fluid_event_channel_pressure(evt, chan, (short)fluid_midi_event_get_program(event));
|
||||
break;
|
||||
|
||||
case KEY_PRESSURE:
|
||||
fluid_event_key_pressure(evt,
|
||||
chan,
|
||||
(short)fluid_midi_event_get_key(event),
|
||||
(short)fluid_midi_event_get_value(event));
|
||||
break;
|
||||
|
||||
case MIDI_SYSTEM_RESET:
|
||||
fluid_event_system_reset(evt);
|
||||
break;
|
||||
|
||||
default: /* Not yet implemented */
|
||||
return FLUID_FAILED;
|
||||
}
|
||||
|
||||
return FLUID_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Accessing event data
|
||||
|
|
|
@ -184,6 +184,8 @@ fluid_mod_get_source_value(const unsigned char mod_src,
|
|||
|
||||
if(mod_flags & FLUID_MOD_CC)
|
||||
{
|
||||
val = fluid_channel_get_cc(chan, mod_src);
|
||||
|
||||
/* From MIDI Recommended Practice (RP-036) Default Pan Formula:
|
||||
* "Since MIDI controller values range from 0 to 127, the exact center
|
||||
* of the range, 63.5, cannot be represented. Therefore, the effective
|
||||
|
@ -197,16 +199,20 @@ fluid_mod_get_source_value(const unsigned char mod_src,
|
|||
if(mod_src == PAN_MSB || mod_src == BALANCE_MSB)
|
||||
{
|
||||
*range = 126;
|
||||
val = fluid_channel_get_cc(chan, mod_src) - 1;
|
||||
val -= 1;
|
||||
|
||||
if(val < 0)
|
||||
{
|
||||
val = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
else if(mod_src == PORTAMENTO_CTRL)
|
||||
{
|
||||
val = fluid_channel_get_cc(chan, mod_src);
|
||||
// an invalid portamento fromkey should be treated as 0 when it's actually used for moulating
|
||||
if(!fluid_channel_is_valid_note(val))
|
||||
{
|
||||
val = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
@ -1557,6 +1557,10 @@ fluid_synth_remove_default_mod(fluid_synth_t *synth, const fluid_mod_t *mod)
|
|||
|
||||
/**
|
||||
* Send a MIDI controller event on a MIDI channel.
|
||||
*
|
||||
* Most CCs are 7-bits wide in FluidSynth. There are a few exceptions which may be 14-bits wide as are documented here:
|
||||
* https://github.com/FluidSynth/fluidsynth/wiki/FluidFeatures#midi-control-change-implementation-chart
|
||||
*
|
||||
* @param synth FluidSynth instance
|
||||
* @param chan MIDI channel number (0 to MIDI channel count - 1)
|
||||
* @param num MIDI controller number (0-127)
|
||||
|
@ -1571,6 +1575,8 @@ fluid_synth_remove_default_mod(fluid_synth_t *synth, const fluid_mod_t *mod)
|
|||
* could be used as CC global for all channels belonging to basic channel 7.
|
||||
* - Let a basic channel 0 in mode 3. If MIDI channel 15 is disabled it could be used
|
||||
* as CC global for all channels belonging to basic channel 0.
|
||||
* @warning Contrary to the MIDI Standard, this function does not clear LSB controllers,
|
||||
* when MSB controllers are received.
|
||||
*/
|
||||
int
|
||||
fluid_synth_cc(fluid_synth_t *synth, int chan, int num, int val)
|
||||
|
@ -1794,6 +1800,9 @@ fluid_synth_cc_LOCAL(fluid_synth_t *synth, int channum, int num)
|
|||
|
||||
case ALL_CTRL_OFF: /* not allowed to modulate (spec SF 2.01 - 8.2.1) */
|
||||
fluid_channel_init_ctrl(chan, 1);
|
||||
// the hold pedals have been reset, we maybe need to release voices
|
||||
fluid_synth_damp_voices_by_sustain_LOCAL(synth, channum);
|
||||
fluid_synth_damp_voices_by_sostenuto_LOCAL(synth, channum);
|
||||
fluid_synth_modulate_voices_all_LOCAL(synth, channum);
|
||||
break;
|
||||
|
||||
|
@ -2371,6 +2380,7 @@ fluid_synth_sysex_gs_dt1(fluid_synth_t *synth, const char *data, int len,
|
|||
|
||||
if(len < 9) // at least one byte of data should be transmitted
|
||||
{
|
||||
FLUID_LOG(FLUID_INFO, "SysEx DT1: message too short, dropping it.");
|
||||
return FLUID_FAILED;
|
||||
}
|
||||
len_data = len - 8;
|
||||
|
@ -2380,8 +2390,10 @@ fluid_synth_sysex_gs_dt1(fluid_synth_t *synth, const char *data, int len,
|
|||
{
|
||||
checksum += data[i];
|
||||
}
|
||||
if (0x80 - (checksum & 0x7F) != data[len - 1])
|
||||
checksum = 0x80 - (checksum & 0x7F);
|
||||
if (checksum != data[len - 1])
|
||||
{
|
||||
FLUID_LOG(FLUID_INFO, "SysEx DT1: dropping message on addr 0x%x due to incorrect checksum 0x%x. Correct checksum: 0x%x", addr, (int)data[len - 1], checksum);
|
||||
return FLUID_FAILED;
|
||||
}
|
||||
|
||||
|
@ -2389,6 +2401,7 @@ fluid_synth_sysex_gs_dt1(fluid_synth_t *synth, const char *data, int len,
|
|||
{
|
||||
if (len_data > 1 || (data[7] != 0 && data[7] != 0x7f))
|
||||
{
|
||||
FLUID_LOG(FLUID_INFO, "SysEx DT1: dropping invalid mode set message");
|
||||
return FLUID_FAILED;
|
||||
}
|
||||
if (handled)
|
||||
|
@ -2419,6 +2432,7 @@ fluid_synth_sysex_gs_dt1(fluid_synth_t *synth, const char *data, int len,
|
|||
{
|
||||
if (len_data > 1 || data[7] > 0x02)
|
||||
{
|
||||
FLUID_LOG(FLUID_INFO, "SysEx DT1: dropping invalid rhythm part message");
|
||||
return FLUID_FAILED;
|
||||
}
|
||||
if (handled)
|
||||
|
@ -2433,6 +2447,7 @@ fluid_synth_sysex_gs_dt1(fluid_synth_t *synth, const char *data, int len,
|
|||
synth->channel[chan]->channel_type =
|
||||
data[7] == 0x00 ? CHANNEL_TYPE_MELODIC : CHANNEL_TYPE_DRUM;
|
||||
|
||||
FLUID_LOG(FLUID_DBG, "SysEx DT1: setting MIDI channel %d to type %d", chan, (int)synth->channel[chan]->channel_type);
|
||||
//Roland synths seem to "remember" the last instrument a channel
|
||||
//used in the selected mode. This behavior is not replicated here.
|
||||
fluid_synth_program_change(synth, chan, 0);
|
||||
|
@ -3702,7 +3717,8 @@ fluid_synth_get_active_voice_count(fluid_synth_t *synth)
|
|||
* @param synth FluidSynth instance
|
||||
* @return Internal buffer size in audio frames.
|
||||
*
|
||||
* Audio is synthesized this number of frames at a time. Defaults to 64 frames.
|
||||
* Audio is synthesized at this number of frames at a time. Defaults to 64 frames. I.e. the synth can only react to notes,
|
||||
* control changes, and other audio affecting events after having processed 64 audio frames.
|
||||
*/
|
||||
int
|
||||
fluid_synth_get_internal_bufsize(fluid_synth_t *synth)
|
||||
|
|
|
@ -1110,8 +1110,9 @@ fluid_voice_update_param(fluid_voice_t *voice, int gen)
|
|||
/* Modulation envelope */
|
||||
case GEN_MODENVDELAY: /* SF2.01 section 8.1.3 # 25 */
|
||||
fluid_clip(x, -12000.0f, 5000.0f);
|
||||
count = NUM_BUFFERS_DELAY(x);
|
||||
fluid_voice_update_modenv(voice, TRUE, FLUID_VOICE_ENVDELAY,
|
||||
NUM_BUFFERS_DELAY(x), 0.0f, 0.0f, -1.0f, 1.0f);
|
||||
count, 0.0f, 0.0f, -1.0f, 1.0f);
|
||||
break;
|
||||
|
||||
case GEN_MODENVATTACK: /* SF2.01 section 8.1.3 # 26 */
|
||||
|
|
|
@ -22,6 +22,10 @@
|
|||
#ifndef _FLUID_SETTINGS_H
|
||||
#define _FLUID_SETTINGS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int fluid_settings_add_option(fluid_settings_t *settings, const char *name, const char *s);
|
||||
int fluid_settings_remove_option(fluid_settings_t *settings, const char *name, const char *s);
|
||||
|
||||
|
@ -54,4 +58,8 @@ int fluid_settings_split_csv(const char *str, int *buf, int buf_len);
|
|||
|
||||
void* fluid_settings_get_user_data(fluid_settings_t * settings, const char *name);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _FLUID_SETTINGS_H */
|
||||
|
|
|
@ -387,17 +387,17 @@ void fluid_msleep(unsigned int msecs)
|
|||
*/
|
||||
unsigned int fluid_curtime(void)
|
||||
{
|
||||
float now;
|
||||
static float initial_time = 0;
|
||||
double now;
|
||||
static double initial_time = 0;
|
||||
|
||||
if(initial_time == 0)
|
||||
{
|
||||
initial_time = (float)fluid_utime();
|
||||
initial_time = fluid_utime();
|
||||
}
|
||||
|
||||
now = (float)fluid_utime();
|
||||
now = fluid_utime();
|
||||
|
||||
return (unsigned int)((now - initial_time) / 1000.0f);
|
||||
return (unsigned int)((now - initial_time) / 1000.0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1730,14 +1730,14 @@ FILE* fluid_file_open(const char* path, const char** errMsg)
|
|||
|
||||
FILE* handle = NULL;
|
||||
|
||||
if(!g_file_test(path, G_FILE_TEST_EXISTS))
|
||||
if(!fluid_file_test(path, FLUID_FILE_TEST_EXISTS))
|
||||
{
|
||||
if(errMsg != NULL)
|
||||
{
|
||||
*errMsg = ErrExist;
|
||||
}
|
||||
}
|
||||
else if(!g_file_test(path, G_FILE_TEST_IS_REGULAR))
|
||||
else if(!fluid_file_test(path, FLUID_FILE_TEST_IS_REGULAR))
|
||||
{
|
||||
if(errMsg != NULL)
|
||||
{
|
||||
|
|
|
@ -132,6 +132,9 @@ typedef gintptr intptr_t;
|
|||
#if defined(WIN32) && HAVE_WINDOWS_H
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h> /* Provides also socklen_t */
|
||||
#ifdef WITH_GLIB_STUBS
|
||||
#include "win32_glibstubs.h"
|
||||
#endif
|
||||
|
||||
/* WIN32 special defines */
|
||||
#define STDIN_FILENO 0
|
||||
|
@ -157,7 +160,9 @@ typedef gintptr intptr_t;
|
|||
#include <gmodule.h>
|
||||
#endif
|
||||
|
||||
#ifndef WIN32
|
||||
#include <glib/gstdio.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Macro used for safely accessing a message from a GError and using a default
|
||||
|
@ -200,6 +205,12 @@ char* fluid_get_windows_error(void);
|
|||
*/
|
||||
char *fluid_strtok(char **str, char *delim);
|
||||
|
||||
#define FLUID_FILE_TEST_EXISTS G_FILE_TEST_EXISTS
|
||||
#define FLUID_FILE_TEST_IS_REGULAR G_FILE_TEST_IS_REGULAR
|
||||
#define fluid_file_test(path, flags) g_file_test(path, flags)
|
||||
|
||||
#define fluid_shell_parse_argv(command_line, argcp, argvp) g_shell_parse_argv(command_line, argcp, argvp, NULL)
|
||||
#define fluid_strfreev g_strfreev
|
||||
|
||||
#if defined(__OS2__)
|
||||
#define INCL_DOS
|
||||
|
|
|
@ -29,10 +29,12 @@
|
|||
#ifndef _FLUIDSYNTH_PRIV_H
|
||||
#define _FLUIDSYNTH_PRIV_H
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef WITH_GLIB_STUBS
|
||||
#include <glib.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_STDLIB_H
|
||||
#include <stdlib.h> // malloc, free
|
||||
#endif
|
||||
|
@ -48,6 +50,9 @@
|
|||
|
||||
#include "fluidsynth.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
|
@ -70,8 +75,13 @@ typedef double fluid_real_t;
|
|||
|
||||
|
||||
/** Atomic types */
|
||||
#if defined(WIN32) && defined(WITH_GLIB_STUBS)
|
||||
typedef long fluid_atomic_int_t;
|
||||
typedef unsigned long fluid_atomic_uint_t;
|
||||
#else
|
||||
typedef int fluid_atomic_int_t;
|
||||
typedef unsigned int fluid_atomic_uint_t;
|
||||
#endif
|
||||
typedef float fluid_atomic_float_t;
|
||||
|
||||
|
||||
|
@ -318,5 +328,8 @@ else \
|
|||
#define fluid_return_val_if_fail(cond, val) \
|
||||
fluid_return_if_fail(cond) (val)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _FLUIDSYNTH_PRIV_H */
|
||||
|
|
261
src/utils/win32_glibstubs.c
Normal file
261
src/utils/win32_glibstubs.c
Normal file
|
@ -0,0 +1,261 @@
|
|||
#ifdef WIN32
|
||||
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
|
||||
#include "fluidsynth_priv.h"
|
||||
#include "fluid_sys.h"
|
||||
#include "win32_glibstubs.h"
|
||||
|
||||
#include <process.h>
|
||||
|
||||
static wchar_t *utf8_to_wc(const char *str)
|
||||
{
|
||||
if (str == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
wchar_t *wstr = NULL;
|
||||
int length;
|
||||
|
||||
if ((length = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, str, -1, NULL, 0)) == 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
wstr = malloc(length * sizeof(wchar_t));
|
||||
if (wstr == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, str, -1, wstr, length);
|
||||
return wstr;
|
||||
}
|
||||
|
||||
BOOL fluid_g_file_test(const char *pathA, int flags)
|
||||
{
|
||||
wchar_t *path = utf8_to_wc(pathA);
|
||||
if (path == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
DWORD attributes = GetFileAttributesW(path);
|
||||
FLUID_FREE(path);
|
||||
if (attributes == INVALID_FILE_ATTRIBUTES)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
if (flags & G_FILE_TEST_EXISTS)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
if (flags & G_FILE_TEST_IS_REGULAR)
|
||||
{
|
||||
return (attributes & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_DEVICE)) == 0;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// ParseCommandLine - Taken from ZDoom
|
||||
//
|
||||
// Parse a command line (passed in args). If argc is non-NULL, it will
|
||||
// be set to the number of arguments. If argv is non-NULL, it will be
|
||||
// filled with pointers to each argument; argv[0] should be initialized
|
||||
// to point to a buffer large enough to hold all the arguments. The
|
||||
// return value is the necessary size of this buffer.
|
||||
//
|
||||
// Special processing:
|
||||
// Inside quoted strings, \" becomes just "
|
||||
// \\ becomes just a single backslash
|
||||
|
||||
static long ParseCommandLine(const char *args, int *argc, char **argv)
|
||||
{
|
||||
int count;
|
||||
char *buffer;
|
||||
long buffplace;
|
||||
|
||||
count = 0;
|
||||
buffplace = 0;
|
||||
buffer = argv != NULL ? argv[0] : NULL;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
while (*args <= ' ' && *args)
|
||||
{ // skip white space
|
||||
args++;
|
||||
}
|
||||
if (*args == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (*args == '\"')
|
||||
{ // read quoted string
|
||||
char stuff;
|
||||
if (argv != NULL)
|
||||
{
|
||||
argv[count] = buffer + buffplace;
|
||||
}
|
||||
count++;
|
||||
args++;
|
||||
do
|
||||
{
|
||||
stuff = *args++;
|
||||
if (stuff == '\\' && *args == '\"')
|
||||
{
|
||||
stuff = '\"';
|
||||
args++;
|
||||
}
|
||||
else if (stuff == '\\' && *args == '\\')
|
||||
{
|
||||
args++;
|
||||
}
|
||||
else if (stuff == '\"')
|
||||
{
|
||||
stuff = 0;
|
||||
}
|
||||
else if (stuff == 0)
|
||||
{
|
||||
args--;
|
||||
}
|
||||
if (argv != NULL)
|
||||
{
|
||||
buffer[buffplace] = stuff;
|
||||
}
|
||||
buffplace++;
|
||||
} while (stuff);
|
||||
}
|
||||
else
|
||||
{ // read unquoted string
|
||||
const char *start = args++, *end;
|
||||
|
||||
while (*args && *args > ' ' && *args != '\"')
|
||||
{
|
||||
args++;
|
||||
}
|
||||
end = args;
|
||||
if (argv != NULL)
|
||||
{
|
||||
argv[count] = buffer + buffplace;
|
||||
while (start < end)
|
||||
{
|
||||
buffer[buffplace++] = *start++;
|
||||
}
|
||||
buffer[buffplace++] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
buffplace += end - start + 1;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
}
|
||||
if (argc != NULL)
|
||||
{
|
||||
*argc = count;
|
||||
}
|
||||
return buffplace;
|
||||
}
|
||||
|
||||
BOOL fluid_g_shell_parse_argv(const char *command_line, int *argcp, char ***argvp, void *_)
|
||||
{
|
||||
long argsize = ParseCommandLine(command_line, argcp, NULL);
|
||||
*argvp = NULL;
|
||||
if (*argcp != 0)
|
||||
{
|
||||
*argvp = (char **)malloc(*argcp * sizeof(char *) + argsize);
|
||||
if (!*argvp)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
**argvp = (char *)*argvp + *argcp * sizeof(char *);
|
||||
ParseCommandLine(command_line, NULL, *argvp);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
double fluid_g_get_monotonic_time(void)
|
||||
{
|
||||
static LARGE_INTEGER freq_cache = { 0, 0 }; /* Performance Frequency */
|
||||
LARGE_INTEGER perf_cpt;
|
||||
|
||||
if (!freq_cache.QuadPart)
|
||||
{
|
||||
QueryPerformanceFrequency(&freq_cache); /* Frequency value */
|
||||
}
|
||||
|
||||
QueryPerformanceCounter(&perf_cpt); /* Counter value */
|
||||
return perf_cpt.QuadPart * 1000000.0 / freq_cache.QuadPart; /* time in micros */
|
||||
}
|
||||
|
||||
/* Thread support */
|
||||
static unsigned __stdcall g_thread_wrapper(void *info_)
|
||||
{
|
||||
GThread *info = (GThread *)info_;
|
||||
info->func(info->data);
|
||||
/* Free the "GThread" now if it was detached. Otherwise, it's freed in fluid_g_thread_join. */
|
||||
if (info->handle == NULL)
|
||||
{
|
||||
free(info);
|
||||
}
|
||||
_endthreadex(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
GThread *fluid_g_thread_create(GThreadFunc func, void *data, BOOL joinable, GError **error)
|
||||
{
|
||||
static GError error_container;
|
||||
|
||||
g_return_val_if_fail(func != NULL, NULL);
|
||||
|
||||
GThread *info = (GThread *)malloc(sizeof(GThread));
|
||||
if (info == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
info->func = func;
|
||||
info->data = data;
|
||||
|
||||
HANDLE thread = (HANDLE)_beginthreadex(NULL, 0, g_thread_wrapper, info, CREATE_SUSPENDED, NULL);
|
||||
|
||||
if (error != NULL)
|
||||
{
|
||||
error_container.code = thread ? 0 : errno;
|
||||
if (errno != 0)
|
||||
{
|
||||
error_container.message = strerror(errno);
|
||||
}
|
||||
*error = &error_container;
|
||||
}
|
||||
|
||||
if (thread == NULL)
|
||||
{
|
||||
free(info);
|
||||
info = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!joinable)
|
||||
{
|
||||
/* Release thread reference, if caller doesn't want to join */
|
||||
CloseHandle(thread);
|
||||
info->handle = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
info->handle = thread;
|
||||
}
|
||||
ResumeThread(thread);
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
void fluid_g_thread_join(GThread *thread)
|
||||
{
|
||||
if (thread != NULL && thread->handle != NULL)
|
||||
{
|
||||
WaitForSingleObject(thread->handle, INFINITE);
|
||||
CloseHandle(thread->handle);
|
||||
free(thread);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
137
src/utils/win32_glibstubs.h
Normal file
137
src/utils/win32_glibstubs.h
Normal file
|
@ -0,0 +1,137 @@
|
|||
#ifndef _GLIBSTUBS_H
|
||||
#define _GLIBSTUBS_H
|
||||
|
||||
#ifdef WIN32
|
||||
#include <Windows.h>
|
||||
#include <assert.h>
|
||||
|
||||
/* Miscellaneous stubs */
|
||||
#define GLIB_CHECK_VERSION(x, y, z) 0 /* Evaluate to 0 to get FluidSynth to use the "old" thread API */
|
||||
#define GLIB_MAJOR_VERSION 2
|
||||
#define GLIB_MINOR_VERSION 29
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int code;
|
||||
const char *message;
|
||||
} GError;
|
||||
typedef void *gpointer;
|
||||
|
||||
#define g_new(s, c) FLUID_ARRAY(s, c)
|
||||
#define g_free(p) FLUID_FREE(p)
|
||||
#define g_strfreev FLUID_FREE
|
||||
#define g_newa(_type, _len) (_type *)_alloca(sizeof(_type) * (_len))
|
||||
#define g_assert(a) assert(a)
|
||||
#define G_LIKELY(expr) (expr)
|
||||
#define G_UNLIKELY(expr) (expr)
|
||||
#endif
|
||||
|
||||
#define g_return_val_if_fail(expr, val) if (expr) {} else { return val; }
|
||||
#define g_clear_error(err) do {} while (0)
|
||||
|
||||
#define G_FILE_TEST_EXISTS 1
|
||||
#define G_FILE_TEST_IS_REGULAR 2
|
||||
|
||||
#define g_file_test fluid_g_file_test
|
||||
#define g_shell_parse_argv fluid_g_shell_parse_argv
|
||||
BOOL fluid_g_file_test(const char *path, int flags);
|
||||
BOOL fluid_g_shell_parse_argv(const char *command_line, int *argcp, char ***argvp, void *dummy);
|
||||
|
||||
#define g_get_monotonic_time fluid_g_get_monotonic_time
|
||||
double fluid_g_get_monotonic_time(void);
|
||||
|
||||
/* Byte ordering */
|
||||
#ifdef __BYTE_ORDER__
|
||||
#define G_BYTE_ORDER __BYTE_ORDER__
|
||||
#define G_BIG_ENDIAN __ORDER_BIG_ENDIAN__
|
||||
#else
|
||||
// If __BYTE_ORDER__ isn't defined, assume little endian
|
||||
#define G_BYTE_ORDER 1234
|
||||
#define G_BIG_ENDIAN 4321
|
||||
#endif
|
||||
|
||||
#if G_BYTE_ORDER == G_BIG_ENDIAN
|
||||
#define GINT16_FROM_LE(x) (int16_t)(((uint16_t)(x) >> 8) | ((uint16_t)(x) << 8))
|
||||
#define GINT32_FROM_LE(x) (int32_t)((FLUID_LE16TOH(x) << 16) | (FLUID16_LE16TOH(x >> 16)))
|
||||
#else
|
||||
#define GINT32_FROM_LE(x) (x)
|
||||
#define GINT16_FROM_LE(x) (x)
|
||||
|
||||
/* Thread support */
|
||||
#define g_thread_supported() 1
|
||||
#define g_thread_init(_) do {} while (0)
|
||||
#define g_usleep(usecs) Sleep((usecs) / 1000)
|
||||
|
||||
typedef gpointer (*GThreadFunc)(void *data);
|
||||
typedef struct
|
||||
{
|
||||
GThreadFunc func;
|
||||
void *data;
|
||||
HANDLE handle;
|
||||
} GThread;
|
||||
|
||||
#define g_thread_create fluid_g_thread_create
|
||||
#define g_thread_join fluid_g_thread_join
|
||||
GThread *fluid_g_thread_create(GThreadFunc func, void *data, BOOL joinable, GError **error);
|
||||
void fluid_g_thread_join(GThread *thread);
|
||||
|
||||
/* Regular mutex */
|
||||
typedef SRWLOCK GStaticMutex;
|
||||
#define G_STATIC_MUTEX_INIT SRWLOCK_INIT
|
||||
#define g_static_mutex_init(_m) InitializeSRWLock(_m)
|
||||
#define g_static_mutex_free(_m) do {} while (0)
|
||||
#define g_static_mutex_lock(_m) AcquireSRWLockExclusive(_m)
|
||||
#define g_static_mutex_unlock(_m) ReleaseSRWLockExclusive(_m)
|
||||
|
||||
/* Recursive lock capable mutex */
|
||||
typedef CRITICAL_SECTION GStaticRecMutex;
|
||||
#define g_static_rec_mutex_init(_m) InitializeCriticalSection(_m)
|
||||
#define g_static_rec_mutex_free(_m) DeleteCriticalSection(_m)
|
||||
#define g_static_rec_mutex_lock(_m) EnterCriticalSection(_m)
|
||||
#define g_static_rec_mutex_unlock(_m) LeaveCriticalSection(_m)
|
||||
|
||||
/* Dynamically allocated mutex suitable for fluid_cond_t use */
|
||||
typedef SRWLOCK GMutex;
|
||||
#define g_mutex_free(m) do { if (m != NULL) g_free(m); } while(0)
|
||||
#define g_mutex_lock(m) AcquireSRWLockExclusive(m)
|
||||
#define g_mutex_unlock(m) ReleaseSRWLockExclusive(m)
|
||||
|
||||
static inline GMutex *g_mutex_new(void)
|
||||
{
|
||||
GMutex *mutex = g_new(GMutex, 1);
|
||||
InitializeSRWLock(mutex);
|
||||
return mutex;
|
||||
}
|
||||
|
||||
/* Thread condition signaling */
|
||||
typedef CONDITION_VARIABLE GCond;
|
||||
#define g_cond_free(cond) do { if (cond != NULL) g_free(cond); } while (0)
|
||||
#define g_cond_signal(cond) WakeConditionVariable(cond)
|
||||
#define g_cond_broadcast(cond) WakeAllConditionVariable(cond)
|
||||
#define g_cond_wait(cond, mutex) SleepConditionVariableSRW(cond, mutex, INFINITE, 0)
|
||||
|
||||
static inline GCond *g_cond_new(void)
|
||||
{
|
||||
GCond *cond = g_new(GCond, 1);
|
||||
InitializeConditionVariable(cond);
|
||||
return cond;
|
||||
}
|
||||
|
||||
/* Thread private data */
|
||||
typedef DWORD GStaticPrivate;
|
||||
#define g_static_private_init(_priv) do { *_priv = TlsAlloc(); } while (0)
|
||||
#define g_static_private_get(_priv) TlsGetValue(*_priv)
|
||||
#define g_static_private_set(_priv, _data, _) TlsSetValue(*_priv, _data)
|
||||
#define g_static_private_free(_priv) TlsFree(*_priv)
|
||||
|
||||
/* Atomic operations */
|
||||
#define g_atomic_int_inc(_pi) InterlockedIncrement(_pi)
|
||||
#define g_atomic_int_get(_pi) (MemoryBarrier(), *_pi)
|
||||
#define g_atomic_int_set(_pi, _val) do { MemoryBarrier(); *_pi = _val; } while (0)
|
||||
#define g_atomic_int_dec_and_test(_pi) (InterlockedDecrement(_pi) == 0)
|
||||
#define g_atomic_int_compare_and_exchange(_pi, _old, _new) (InterlockedCompareExchange(_pi, _new, _old) == _old)
|
||||
#define g_atomic_int_exchange_and_add(_pi, _add) InterlockedExchangeAdd(_pi, _add)
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -7,6 +7,7 @@ add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} -C $<CONFIG> --output-on
|
|||
|
||||
|
||||
## add unit tests here ##
|
||||
ADD_FLUID_TEST(test_synth_reset_cc)
|
||||
ADD_FLUID_TEST(test_sample_cache)
|
||||
ADD_FLUID_TEST(test_sfont_loading)
|
||||
ADD_FLUID_TEST(test_sample_rate_change)
|
||||
|
|
|
@ -6,6 +6,13 @@
|
|||
|
||||
#include <limits.h>
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
static short order = 0;
|
||||
void callback_stable_sort(unsigned int time, fluid_event_t *event, fluid_sequencer_t *seq, void *data)
|
||||
{
|
||||
|
|
146
test/test_synth_reset_cc.c
Normal file
146
test/test_synth_reset_cc.c
Normal file
|
@ -0,0 +1,146 @@
|
|||
|
||||
#include "test.h"
|
||||
#include "fluidsynth.h"
|
||||
#include "fluidsynth_priv.h"
|
||||
#include "fluid_synth.h"
|
||||
#include "fluid_midi.h"
|
||||
#include "fluid_chan.h"
|
||||
#include <string.h>
|
||||
|
||||
// render enough samples to go past the release phase of the voice
|
||||
enum { SAMPLES=100*1024 };
|
||||
|
||||
static void test_sustain(fluid_synth_t* synth, int chan)
|
||||
{
|
||||
// depress sustain pedal
|
||||
TEST_SUCCESS(fluid_synth_cc(synth, chan, SUSTAIN_SWITCH, 127));
|
||||
TEST_SUCCESS(fluid_synth_process(synth, SAMPLES, 0, NULL, 0, NULL));
|
||||
|
||||
// hit a note, after some (render-)time has passed
|
||||
TEST_SUCCESS(fluid_synth_noteon(synth, chan, 60, 127));
|
||||
|
||||
// trigger the dsp loop to force rvoice creation
|
||||
TEST_SUCCESS(fluid_synth_process(synth, SAMPLES, 0, NULL, 0, NULL));
|
||||
|
||||
// one voice must be playing by now
|
||||
TEST_ASSERT(fluid_synth_get_active_voice_count(synth) == 2);
|
||||
|
||||
// send noteoff
|
||||
TEST_SUCCESS(fluid_synth_noteoff(synth, chan, 60));
|
||||
|
||||
// voice stays on
|
||||
TEST_SUCCESS(fluid_synth_process(synth, SAMPLES, 0, NULL, 0, NULL));
|
||||
TEST_ASSERT(fluid_synth_get_active_voice_count(synth) == 2);
|
||||
|
||||
// reset controllers
|
||||
TEST_SUCCESS(fluid_synth_cc(synth, chan, ALL_CTRL_OFF, 0));
|
||||
|
||||
// voice should be off now
|
||||
TEST_SUCCESS(fluid_synth_process(synth, SAMPLES, 0, NULL, 0, NULL));
|
||||
TEST_ASSERT(fluid_synth_get_active_voice_count(synth) == 0);
|
||||
}
|
||||
|
||||
static void test_sostenuto(fluid_synth_t *synth, int chan)
|
||||
{
|
||||
// play a note
|
||||
TEST_SUCCESS(fluid_synth_noteon(synth, chan, 60, 127));
|
||||
TEST_SUCCESS(fluid_synth_process(synth, SAMPLES, 0, NULL, 0, NULL));
|
||||
|
||||
// depress sostenuto pedal
|
||||
TEST_ASSERT(fluid_synth_get_active_voice_count(synth) == 2);
|
||||
TEST_SUCCESS(fluid_synth_cc(synth, chan, SOSTENUTO_SWITCH, 127));
|
||||
|
||||
// send noteoff right afterwards
|
||||
TEST_SUCCESS(fluid_synth_noteoff(synth, chan, 60));
|
||||
|
||||
// voice stays on after rendering
|
||||
TEST_SUCCESS(fluid_synth_process(synth, SAMPLES, 0, NULL, 0, NULL));
|
||||
TEST_ASSERT(fluid_synth_get_active_voice_count(synth) == 2);
|
||||
|
||||
// reset controllers
|
||||
TEST_SUCCESS(fluid_synth_cc(synth, chan, ALL_CTRL_OFF, 0));
|
||||
|
||||
// voice should be off now
|
||||
TEST_SUCCESS(fluid_synth_process(synth, SAMPLES, 0, NULL, 0, NULL));
|
||||
TEST_ASSERT(fluid_synth_get_active_voice_count(synth) == 0);
|
||||
}
|
||||
|
||||
static void test_portamento_fromkey(fluid_synth_t* synth, int chan)
|
||||
{
|
||||
int ptc;
|
||||
|
||||
// Portamento is disabled
|
||||
TEST_SUCCESS(fluid_synth_cc(synth, chan, PORTAMENTO_CTRL, 127));
|
||||
TEST_SUCCESS(fluid_synth_get_cc(synth, chan, PORTAMENTO_CTRL, &ptc));
|
||||
TEST_ASSERT(ptc == 127);
|
||||
|
||||
TEST_SUCCESS(fluid_synth_cc(synth, chan, ALL_CTRL_OFF, 0));
|
||||
|
||||
// Because PTC is used for modulating, it should be reset to zero
|
||||
TEST_SUCCESS(fluid_synth_get_cc(synth, chan, PORTAMENTO_CTRL, &ptc));
|
||||
TEST_ASSERT(!fluid_channel_is_valid_note(ptc));
|
||||
|
||||
// Enable Portamento
|
||||
TEST_SUCCESS(fluid_synth_cc(synth, chan, PORTAMENTO_SWITCH, 64));
|
||||
TEST_SUCCESS(fluid_synth_cc(synth, chan, PORTAMENTO_TIME_MSB, 10));
|
||||
TEST_SUCCESS(fluid_synth_get_cc(synth, chan, PORTAMENTO_SWITCH, &ptc));
|
||||
TEST_ASSERT(ptc == 64);
|
||||
TEST_SUCCESS(fluid_synth_get_cc(synth, chan, PORTAMENTO_TIME_MSB, &ptc));
|
||||
TEST_ASSERT(ptc == 10);
|
||||
|
||||
TEST_SUCCESS(fluid_synth_cc(synth, chan, ALL_CTRL_OFF, 0));
|
||||
TEST_SUCCESS(fluid_synth_get_cc(synth, chan, PORTAMENTO_CTRL, &ptc));
|
||||
TEST_ASSERT(!fluid_channel_is_valid_note(ptc));
|
||||
TEST_SUCCESS(fluid_synth_get_cc(synth, chan, PORTAMENTO_SWITCH, &ptc));
|
||||
TEST_ASSERT(ptc == 0);
|
||||
TEST_SUCCESS(fluid_synth_get_cc(synth, chan, PORTAMENTO_TIME_MSB, &ptc));
|
||||
TEST_ASSERT(ptc == 0);
|
||||
|
||||
// Portamento is disabled
|
||||
TEST_SUCCESS(fluid_synth_cc(synth, chan, PORTAMENTO_CTRL, 127));
|
||||
TEST_SUCCESS(fluid_synth_get_cc(synth, chan, PORTAMENTO_CTRL, &ptc));
|
||||
TEST_ASSERT(ptc == 127);
|
||||
|
||||
TEST_SUCCESS(fluid_synth_cc(synth, chan, ALL_CTRL_OFF, 0));
|
||||
|
||||
// Because PTC is used for modulating, it should be reset to zero
|
||||
TEST_SUCCESS(fluid_synth_get_cc(synth, chan, PORTAMENTO_CTRL, &ptc));
|
||||
TEST_ASSERT(!fluid_channel_is_valid_note(ptc));
|
||||
}
|
||||
|
||||
// this test should make sure that sample rate changed are handled correctly
|
||||
int main(void)
|
||||
{
|
||||
int chan;
|
||||
fluid_synth_t *synth;
|
||||
fluid_settings_t *settings = new_fluid_settings();
|
||||
TEST_ASSERT(settings != NULL);
|
||||
|
||||
synth = new_fluid_synth(settings);
|
||||
TEST_ASSERT(synth != NULL);
|
||||
TEST_SUCCESS(fluid_synth_sfload(synth, TEST_SOUNDFONT, 1));
|
||||
|
||||
for (chan = 0; chan < fluid_synth_count_midi_channels(synth); chan++)
|
||||
{
|
||||
const fluid_channel_t* channel = synth->channel[chan];
|
||||
if(channel->channel_type == CHANNEL_TYPE_DRUM)
|
||||
{
|
||||
// drum channels won't spawn voices
|
||||
continue;
|
||||
}
|
||||
|
||||
test_portamento_fromkey(synth, chan);
|
||||
fluid_synth_system_reset(synth);
|
||||
|
||||
test_sustain(synth, chan);
|
||||
fluid_synth_system_reset(synth);
|
||||
|
||||
test_sostenuto(synth, chan);
|
||||
fluid_synth_system_reset(synth);
|
||||
}
|
||||
|
||||
delete_fluid_synth(synth);
|
||||
delete_fluid_settings(settings);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
Loading…
Reference in a new issue