mirror of
https://github.com/ZDoom/fluidsynth.git
synced 2024-12-11 05:11:33 +00:00
Merge branch 'master' into cmake-modernization
This commit is contained in:
commit
d47f53518e
13 changed files with 417 additions and 26 deletions
|
@ -184,19 +184,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
|
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'
|
sudo apt-add-repository 'deb https://apt.kitware.com/ubuntu/ focal main'
|
||||||
displayName: 'Use recent CMake Version'
|
displayName: 'Use recent CMake Version'
|
||||||
condition: ne(variables.CACHE_RESTORED, 'true')
|
condition: and(succeeded(), ne(variables.CACHE_RESTORED, 'true'))
|
||||||
enabled: 'false'
|
enabled: 'false'
|
||||||
|
|
||||||
- script: |
|
- script: |
|
||||||
sudo apt-get update -y
|
sudo apt-get update -y
|
||||||
displayName: 'Update apt'
|
displayName: 'Update apt'
|
||||||
condition: ne(variables.CACHE_RESTORED, 'true')
|
condition: and(succeeded(), ne(variables.CACHE_RESTORED, 'true'))
|
||||||
|
|
||||||
- script: |
|
- script: |
|
||||||
set -ex
|
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
|
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'
|
displayName: 'apt-get install'
|
||||||
condition: ne(variables.CACHE_RESTORED, 'true')
|
condition: and(succeeded(), ne(variables.CACHE_RESTORED, 'true'))
|
||||||
|
|
||||||
- script: |
|
- script: |
|
||||||
set -e
|
set -e
|
||||||
|
@ -260,7 +260,7 @@ jobs:
|
||||||
|
|
||||||
displayName: 'Compile libiconv'
|
displayName: 'Compile libiconv'
|
||||||
workingDirectory: $(DEV)
|
workingDirectory: $(DEV)
|
||||||
condition: ne(variables.CACHE_RESTORED, 'true')
|
condition: and(succeeded(), ne(variables.CACHE_RESTORED, 'true'))
|
||||||
|
|
||||||
- script: |
|
- script: |
|
||||||
set -ex
|
set -ex
|
||||||
|
@ -276,7 +276,7 @@ jobs:
|
||||||
popd
|
popd
|
||||||
displayName: 'Compile libffi'
|
displayName: 'Compile libffi'
|
||||||
workingDirectory: $(DEV)
|
workingDirectory: $(DEV)
|
||||||
condition: ne(variables.CACHE_RESTORED, 'true')
|
condition: and(succeeded(), ne(variables.CACHE_RESTORED, 'true'))
|
||||||
|
|
||||||
- script: |
|
- script: |
|
||||||
set -ex
|
set -ex
|
||||||
|
@ -400,7 +400,7 @@ jobs:
|
||||||
popd
|
popd
|
||||||
displayName: 'Compile gettext'
|
displayName: 'Compile gettext'
|
||||||
workingDirectory: $(DEV)
|
workingDirectory: $(DEV)
|
||||||
condition: ne(variables.CACHE_RESTORED, 'true')
|
condition: and(succeeded(), ne(variables.CACHE_RESTORED, 'true'))
|
||||||
|
|
||||||
- script: |
|
- script: |
|
||||||
set -ex
|
set -ex
|
||||||
|
@ -463,7 +463,7 @@ jobs:
|
||||||
popd
|
popd
|
||||||
displayName: 'Compile glib'
|
displayName: 'Compile glib'
|
||||||
workingDirectory: $(DEV)
|
workingDirectory: $(DEV)
|
||||||
condition: ne(variables.CACHE_RESTORED, 'true')
|
condition: and(succeeded(), ne(variables.CACHE_RESTORED, 'true'))
|
||||||
|
|
||||||
- template: cmake-android.yml
|
- template: cmake-android.yml
|
||||||
parameters:
|
parameters:
|
||||||
|
@ -559,7 +559,7 @@ jobs:
|
||||||
|
|
||||||
displayName: 'Create fake oboe.pc'
|
displayName: 'Create fake oboe.pc'
|
||||||
workingDirectory: $(DEV)
|
workingDirectory: $(DEV)
|
||||||
condition: ne(variables.CACHE_RESTORED, 'true')
|
condition: and(succeeded(), ne(variables.CACHE_RESTORED, 'true'))
|
||||||
|
|
||||||
- template: cmake-android.yml
|
- template: cmake-android.yml
|
||||||
parameters:
|
parameters:
|
||||||
|
|
|
@ -20,9 +20,6 @@ jobs:
|
||||||
UnixLibs:
|
UnixLibs:
|
||||||
imageName: 'macos-11'
|
imageName: 'macos-11'
|
||||||
CMakeFlags: '-Denable-framework=0'
|
CMakeFlags: '-Denable-framework=0'
|
||||||
10_14:
|
|
||||||
imageName: 'macOS-10.14'
|
|
||||||
CMakeFlags: ''
|
|
||||||
10_15:
|
10_15:
|
||||||
imageName: 'macOS-10.15'
|
imageName: 'macOS-10.15'
|
||||||
CMakeFlags: ''
|
CMakeFlags: ''
|
||||||
|
|
|
@ -69,17 +69,17 @@ jobs:
|
||||||
# ninja --version
|
# ninja --version
|
||||||
cmake --version
|
cmake --version
|
||||||
rm -rf C:/Strawberry/perl/bin/pkg-config*
|
rm -rf C:/Strawberry/perl/bin/pkg-config*
|
||||||
choco install --svc --sdc -i pkgconfiglite &
|
choco install --svc --sdc -i pkgconfiglite
|
||||||
chocoTask=$!
|
# chocoTask=$!
|
||||||
# manually update vcpkg
|
# manually update vcpkg
|
||||||
cd $VCPKG_INSTALLATION_ROOT
|
cd $VCPKG_INSTALLATION_ROOT
|
||||||
# git checkout master
|
# git checkout master
|
||||||
git remote -v
|
git remote -v
|
||||||
git fetch --unshallow --tags --prune --progress origin
|
git fetch --tags --prune --progress origin
|
||||||
git checkout --force $(VCPKG_REVISION)
|
git checkout --force $(VCPKG_REVISION)
|
||||||
sed -i 's/arm64/arm/g' ports/glib/portfile.cmake
|
sed -i 's/arm64/arm/g' ports/glib/portfile.cmake
|
||||||
./bootstrap-vcpkg.sh
|
./bootstrap-vcpkg.sh
|
||||||
wait $chocoTask
|
# wait $chocoTask
|
||||||
which pkg-config
|
which pkg-config
|
||||||
displayName: 'Update vcpkg'
|
displayName: 'Update vcpkg'
|
||||||
- task: DownloadBuildArtifacts@0
|
- task: DownloadBuildArtifacts@0
|
||||||
|
|
|
@ -41,7 +41,7 @@ set ( PACKAGE "fluidsynth" )
|
||||||
# FluidSynth package version
|
# FluidSynth package version
|
||||||
set ( FLUIDSYNTH_VERSION_MAJOR 2 )
|
set ( FLUIDSYNTH_VERSION_MAJOR 2 )
|
||||||
set ( FLUIDSYNTH_VERSION_MINOR 2 )
|
set ( FLUIDSYNTH_VERSION_MINOR 2 )
|
||||||
set ( FLUIDSYNTH_VERSION_MICRO 3 )
|
set ( FLUIDSYNTH_VERSION_MICRO 4 )
|
||||||
set ( VERSION "${FLUIDSYNTH_VERSION_MAJOR}.${FLUIDSYNTH_VERSION_MINOR}.${FLUIDSYNTH_VERSION_MICRO}" )
|
set ( VERSION "${FLUIDSYNTH_VERSION_MAJOR}.${FLUIDSYNTH_VERSION_MINOR}.${FLUIDSYNTH_VERSION_MICRO}" )
|
||||||
set ( FLUIDSYNTH_VERSION "\"${VERSION}\"" )
|
set ( FLUIDSYNTH_VERSION "\"${VERSION}\"" )
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ set ( FLUIDSYNTH_VERSION "\"${VERSION}\"" )
|
||||||
# This is not exactly the same algorithm as the libtool one, but the results are the same.
|
# 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_CURRENT 3 )
|
||||||
set ( LIB_VERSION_AGE 0 )
|
set ( LIB_VERSION_AGE 0 )
|
||||||
set ( LIB_VERSION_REVISION 3 )
|
set ( LIB_VERSION_REVISION 4 )
|
||||||
set ( LIB_VERSION_INFO
|
set ( LIB_VERSION_INFO
|
||||||
"${LIB_VERSION_CURRENT}.${LIB_VERSION_AGE}.${LIB_VERSION_REVISION}" )
|
"${LIB_VERSION_CURRENT}.${LIB_VERSION_AGE}.${LIB_VERSION_REVISION}" )
|
||||||
|
|
||||||
|
@ -89,6 +89,7 @@ option ( enable-waveout "compile Windows WaveOut support (if it is available)" o
|
||||||
option ( enable-winmidi "compile Windows MIDI 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-sdl2 "compile SDL2 audio support (if it is available)" on )
|
||||||
option ( enable-pulseaudio "compile PulseAudio support (if it is available)" 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-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-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 )
|
option ( enable-openmp "enable OpenMP support (parallelization of soundfont decoding, vectorization of voice mixing, etc.)" on )
|
||||||
|
@ -563,6 +564,14 @@ else ( enable-jack )
|
||||||
unset_pkg_config ( JACK )
|
unset_pkg_config ( JACK )
|
||||||
endif ( enable-jack )
|
endif ( enable-jack )
|
||||||
|
|
||||||
|
unset ( PIPEWIRE_SUPPORT CACHE )
|
||||||
|
if ( enable-pipewire )
|
||||||
|
pkg_check_modules ( PIPEWIRE libpipewire-0.3 )
|
||||||
|
set ( PIPEWIRE_SUPPORT ${PIPEWIRE_FOUND} )
|
||||||
|
else ( enable-pipewire )
|
||||||
|
unset_pkg_config ( PIPEWIRE )
|
||||||
|
endif ( enable-pipewire )
|
||||||
|
|
||||||
unset ( LASH_SUPPORT CACHE )
|
unset ( LASH_SUPPORT CACHE )
|
||||||
if ( enable-lash )
|
if ( enable-lash )
|
||||||
pkg_check_modules ( LASH lash-1.0>=0.3 IMPORTED_TARGET )
|
pkg_check_modules ( LASH lash-1.0>=0.3 IMPORTED_TARGET )
|
||||||
|
@ -824,8 +833,6 @@ endif ()
|
||||||
|
|
||||||
generate_pkgconfig_spec(fluidsynth.pc.in ${CMAKE_BINARY_DIR}/fluidsynth.pc libfluidsynth-OBJ)
|
generate_pkgconfig_spec(fluidsynth.pc.in ${CMAKE_BINARY_DIR}/fluidsynth.pc libfluidsynth-OBJ)
|
||||||
|
|
||||||
list ( JOIN PC_REQUIRES_PRIV " " PC_REQUIRES_PRIV_JOINED )
|
|
||||||
|
|
||||||
configure_file ( fluidsynth.pc.in
|
configure_file ( fluidsynth.pc.in
|
||||||
${CMAKE_BINARY_DIR}/fluidsynth.pc IMMEDIATE @ONLY )
|
${CMAKE_BINARY_DIR}/fluidsynth.pc IMMEDIATE @ONLY )
|
||||||
install ( FILES ${CMAKE_BINARY_DIR}/fluidsynth.pc
|
install ( FILES ${CMAKE_BINARY_DIR}/fluidsynth.pc
|
||||||
|
|
|
@ -31,6 +31,12 @@ else ( JACK_SUPPORT )
|
||||||
set ( AUDIO_MIDI_REPORT "${AUDIO_MIDI_REPORT} JACK: no\n" )
|
set ( AUDIO_MIDI_REPORT "${AUDIO_MIDI_REPORT} JACK: no\n" )
|
||||||
endif ( JACK_SUPPORT )
|
endif ( JACK_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 ( MIDISHARE_SUPPORT )
|
if ( MIDISHARE_SUPPORT )
|
||||||
set ( AUDIO_MIDI_REPORT "${AUDIO_MIDI_REPORT} MidiShare: yes\n" )
|
set ( AUDIO_MIDI_REPORT "${AUDIO_MIDI_REPORT} MidiShare: yes\n" )
|
||||||
else ( MIDISHARE_SUPPORT )
|
else ( MIDISHARE_SUPPORT )
|
||||||
|
|
|
@ -14,11 +14,6 @@ https://stackoverflow.com/a/6251757
|
||||||
Developers:
|
Developers:
|
||||||
- Settings can be deprecated by adding: <deprecated>SOME TEXT</deprecated>
|
- Settings can be deprecated by adding: <deprecated>SOME TEXT</deprecated>
|
||||||
- Real-time settings can be marked with <realtime>SOME OPTIONAL TEXT</realtime>.
|
- 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"?>
|
<?xml-stylesheet type="text/xsl" href="fluidsettings.xsl"?>
|
||||||
<fluidsettings>
|
<fluidsettings>
|
||||||
|
@ -607,6 +602,30 @@ and commit the results. Refresh with the following command:
|
||||||
Device to use for OSS audio output.
|
Device to use for OSS audio output.
|
||||||
</desc>
|
</desc>
|
||||||
</setting>
|
</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>
|
<setting>
|
||||||
<name>portaudio.device</name>
|
<name>portaudio.device</name>
|
||||||
<type>str</type>
|
<type>str</type>
|
||||||
|
|
|
@ -8,8 +8,8 @@
|
||||||
\author David Henningsson
|
\author David Henningsson
|
||||||
\author Tom Moebert
|
\author Tom Moebert
|
||||||
\author Copyright © 2003-2021 Peter Hanappe, Conrad Berhörster, Antoine Schmitt, Pedro López-Cabanillas, Josh Green, David Henningsson, 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.3
|
\version Revision 2.2.4
|
||||||
\date 2021-09-11
|
\date 2021-11-21
|
||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,11 @@ if ( JACK_SUPPORT )
|
||||||
set ( fluid_jack_SOURCES drivers/fluid_jack.c )
|
set ( fluid_jack_SOURCES drivers/fluid_jack.c )
|
||||||
endif ( JACK_SUPPORT )
|
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 )
|
if ( PORTAUDIO_SUPPORT )
|
||||||
set ( fluid_portaudio_SOURCES drivers/fluid_portaudio.c )
|
set ( fluid_portaudio_SOURCES drivers/fluid_portaudio.c )
|
||||||
endif ( PORTAUDIO_SUPPORT )
|
endif ( PORTAUDIO_SUPPORT )
|
||||||
|
@ -232,6 +237,7 @@ add_library ( libfluidsynth-OBJ OBJECT
|
||||||
${fluid_dart_SOURCES}
|
${fluid_dart_SOURCES}
|
||||||
${fluid_dbus_SOURCES}
|
${fluid_dbus_SOURCES}
|
||||||
${fluid_jack_SOURCES}
|
${fluid_jack_SOURCES}
|
||||||
|
${fluid_pipewire_SOURCES}
|
||||||
${fluid_lash_SOURCES}
|
${fluid_lash_SOURCES}
|
||||||
${fluid_midishare_SOURCES}
|
${fluid_midishare_SOURCES}
|
||||||
${fluid_opensles_SOURCES}
|
${fluid_opensles_SOURCES}
|
||||||
|
@ -322,6 +328,7 @@ endif ( MACOSX_FRAMEWORK )
|
||||||
# Object Libraries may "link" to other libraries to get usage requirements,
|
# 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.
|
# but since they do not have a link step nothing is done with their object files.
|
||||||
target_link_libraries ( libfluidsynth-OBJ PUBLIC
|
target_link_libraries ( libfluidsynth-OBJ PUBLIC
|
||||||
|
${PIPEWIRE_LIBRARIES}
|
||||||
${DART_LIBS}
|
${DART_LIBS}
|
||||||
${COREAUDIO_LIBS}
|
${COREAUDIO_LIBS}
|
||||||
${COREMIDI_LIBS}
|
${COREMIDI_LIBS}
|
||||||
|
|
|
@ -130,6 +130,9 @@
|
||||||
/* Define to enable JACK driver */
|
/* Define to enable JACK driver */
|
||||||
#cmakedefine JACK_SUPPORT @JACK_SUPPORT@
|
#cmakedefine JACK_SUPPORT @JACK_SUPPORT@
|
||||||
|
|
||||||
|
/* Define to enable PipeWire driver */
|
||||||
|
#cmakedefine PIPEWIRE_SUPPORT @PIPEWIRE_SUPPORT@
|
||||||
|
|
||||||
/* Include the LADSPA Fx unit */
|
/* Include the LADSPA Fx unit */
|
||||||
#cmakedefine LADSPA @LADSPA_SUPPORT@
|
#cmakedefine LADSPA @LADSPA_SUPPORT@
|
||||||
|
|
||||||
|
|
|
@ -70,6 +70,16 @@ static const fluid_audriver_definition_t fluid_audio_drivers[] =
|
||||||
},
|
},
|
||||||
#endif
|
#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
|
#if OSS_SUPPORT
|
||||||
{
|
{
|
||||||
"oss",
|
"oss",
|
||||||
|
|
|
@ -138,6 +138,14 @@ void fluid_jack_audio_driver_settings(fluid_settings_t *settings);
|
||||||
int fluid_jack_obtain_synth(fluid_settings_t *settings, fluid_synth_t **synth);
|
int fluid_jack_obtain_synth(fluid_settings_t *settings, fluid_synth_t **synth);
|
||||||
#endif
|
#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
|
#if SNDMAN_SUPPORT
|
||||||
fluid_audio_driver_t *new_fluid_sndmgr_audio_driver(fluid_settings_t *settings,
|
fluid_audio_driver_t *new_fluid_sndmgr_audio_driver(fluid_settings_t *settings,
|
||||||
fluid_synth_t *synth);
|
fluid_synth_t *synth);
|
||||||
|
|
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");
|
||||||
|
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
|
|
@ -2200,6 +2200,9 @@ fluid_player_callback(void *data, unsigned int msec)
|
||||||
* Activates play mode for a MIDI player if not already playing.
|
* Activates play mode for a MIDI player if not already playing.
|
||||||
* @param player MIDI player instance
|
* @param player MIDI player instance
|
||||||
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
|
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
|
||||||
|
*
|
||||||
|
* If the list of files added to the player has completed its requested number of loops,
|
||||||
|
* the playlist will be restarted from the beginning with a loop count of 1.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
fluid_player_play(fluid_player_t *player)
|
fluid_player_play(fluid_player_t *player)
|
||||||
|
@ -2215,10 +2218,17 @@ fluid_player_play(fluid_player_t *player)
|
||||||
fluid_sample_timer_reset(player->synth, player->sample_timer);
|
fluid_sample_timer_reset(player->synth, player->sample_timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If we're at the end of the playlist and there are no loops left, loop once */
|
||||||
|
if(player->currentfile == NULL && player->loop == 0)
|
||||||
|
{
|
||||||
|
player->loop = 1;
|
||||||
|
}
|
||||||
|
|
||||||
fluid_atomic_int_set(&player->status, FLUID_PLAYER_PLAYING);
|
fluid_atomic_int_set(&player->status, FLUID_PLAYER_PLAYING);
|
||||||
|
|
||||||
return FLUID_OK;
|
return FLUID_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pauses the MIDI playback.
|
* Pauses the MIDI playback.
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in a new issue