Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SDL3 Support #1478

Merged
merged 34 commits into from
Feb 8, 2025
Merged

SDL3 Support #1478

merged 34 commits into from
Feb 8, 2025

Conversation

andyvand
Copy link

Add SDL3 support

Add SDL3 support
Copy link
Member

@derselbst derselbst left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow, that was quick. Thanks a lot! I've only got one comment below. Before merging it, I'll adapt the Window CI pipeline in the next days, to make it compile with SDL3 support.

src/drivers/fluid_sdl3.c Outdated Show resolved Hide resolved
.DS_Store Outdated Show resolved Hide resolved
src/.DS_Store Outdated Show resolved Hide resolved
Remove .DS_Store
CMakeLists.txt Outdated Show resolved Hide resolved
cmake_admin/GetSDL3VersionFromHeaders.cmake Outdated Show resolved Hide resolved
src/CMakeLists.txt Outdated Show resolved Hide resolved
CMakeLists.txt Outdated Show resolved Hide resolved
src/drivers/fluid_sdl3.c Show resolved Hide resolved
Fix init SDL3 subsystem
Fix SDL3 linking
Fix for finding SDL3 config and components
Remove SDL3_VERSION not defined check
Remove GetSDL3VersionFromHeaders
Fix init subsystem
Fix return
CMakeLists.txt Outdated Show resolved Hide resolved
Copy link
Member

@derselbst derselbst left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for addressing the review findings. It's getting into shape. I found a few more minor issues.

src/drivers/fluid_sdl3.c Outdated Show resolved Hide resolved
static void
SDLAudioCallback(void *data, SDL_AudioStream *stream, int add_len, int len)
{
void *buffer = malloc(len);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Memory allocation during audio playback is not real-time friendly. Is it possible to calculate the maximum len beforehand and use it to preallocate the biggest possible buffer?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added it to additional len as buffer.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sry, I think you misunderstood me. I was asking to get rid of the malloc from the callback and instead allocate the buffer in new_fluid_sdl3_audio_driver. Also note that dev->write_ptr takes the number of samples (audio frames) to synthesize, not the buffer length in bytes. See here for an example:
https://github.com/libsdl-org/SDL/blob/be991239d9bc6df06b0ca7a9ae9dbb7251e93c12/examples/audio/02-simple-playback-callback/simple-playback-callback.c#L25-L34

Copy link
Author

@andyvand andyvand Feb 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have replaced the malloc with a static buffer and for dev->write_ptr I use the buffer length divided by dev->frame_size

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since it's a static buffer, you may remove the check for NULL in the same function since it generates a warning:

if (buffer == NULL)
{
  return;
}

The actual warning:

fluidsynth/src/drivers/fluid_sdl3.c:165:13: warning: comparison of array 'buffer' equal to a null pointer is always false [-Wtautological-pointer-compare]
if (buffer == NULL)
    ^~~~~~    ~~~~

On the topic of warnings, the following call also triggers a -Wsign-compare warning on clang:

fluidsynth/src/drivers/fluid_sdl3.c:163:19: warning: comparison of integers of different signs: 'int' and 'unsigned long' [-Wsign-compare]
buf_len = SDL_min(add_len, SDL_arraysize(buffer));

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sry for nit-picking again. But you cannot use a buffer with a constant size. The size of the buffer must depend on audio.period-size that you've read in new_fluid_sdl3_audio_driver, otherwise there's no point in reading that setting. I suppose allocating a buffer size of period-size * frame_size would be reasonable.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Buffer got updated to this.
I've added period_size to the dev structure.

Copy link
Author

@andyvand andyvand Feb 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reverted to malloc since the buffer can't be preallocated.
I have put the buffer inside the dev structure.
I have put the creation of the buffer in new_fluid_sdl3_audio_driver and the destruction of the buffer inside delete_fluid_sdl3_audio_driver.

src/drivers/fluid_sdl3.c Outdated Show resolved Hide resolved
src/drivers/fluid_sdl3.c Outdated Show resolved Hide resolved
src/drivers/fluid_sdl3.c Outdated Show resolved Hide resolved
CMakeLists.txt Outdated Show resolved Hide resolved
@derselbst
Copy link
Member

@FtZPetruska I quickly smashed together a Windows CI build that works with SDL3. Even when resolving the cmake issues mentioned above, all the unit tests will be failing because of missing DLL - presumably SDL3.dll, e.g. here

The unit tests inherit their link dependencies from the object lib libfluidsynth-OBJ by linking against it here:

target_link_libraries( ${_test} libfluidsynth-OBJ )

This would carry over all INTERFACE_LINK_LIBRARIES from the object lib to the unit tests. However, when looking at the definition of the sdl3 cmake target, INTERFACE_LINK_LIBRARIES only contains the headers' include dir. The DLL is instead declared by the IMPORTED_LOCATION property, which from my understanding is not used to specify transitive dependencies and therefore isn't carried over from fluidsynth's object lib to the unit test:

add_library(SDL3::SDL3-shared SHARED IMPORTED)
        set_target_properties(SDL3::SDL3-shared
            PROPERTIES
                INTERFACE_LINK_LIBRARIES "SDL3::Headers"
                IMPORTED_IMPLIB "${_sdl3_implib}"
                IMPORTED_LOCATION "${_sdl3_dll}"
                COMPATIBLE_INTERFACE_BOOL "SDL3_SHARED"
                INTERFACE_SDL3_SHARED "ON"
                COMPATIBLE_INTERFACE_STRING "SDL_VERSION"
                INTERFACE_SDL_VERSION "SDL3"
        )

Is my understanding correct? And why isn't _sdl3_dll passed to INTERFACE_LINK_LIBRARIES?

@FtZPetruska
Copy link
Contributor

@FtZPetruska I quickly smashed together a Windows CI build that works with SDL3. Even when resolving the cmake issues mentioned above, all the unit tests will be failing because of missing DLL - presumably SDL3.dll, e.g. here

The unit tests inherit their link dependencies from the object lib libfluidsynth-OBJ by linking against it here:

target_link_libraries( ${_test} libfluidsynth-OBJ )

This would carry over all INTERFACE_LINK_LIBRARIES from the object lib to the unit tests. However, when looking at the definition of the sdl3 cmake target, INTERFACE_LINK_LIBRARIES only contains the headers' include dir. The DLL is instead declared by the IMPORTED_LOCATION property, which from my understanding is not used to specify transitive dependencies and therefore isn't carried over from fluidsynth's object lib to the unit test:

add_library(SDL3::SDL3-shared SHARED IMPORTED)
        set_target_properties(SDL3::SDL3-shared
            PROPERTIES
                INTERFACE_LINK_LIBRARIES "SDL3::Headers"
                IMPORTED_IMPLIB "${_sdl3_implib}"
                IMPORTED_LOCATION "${_sdl3_dll}"
                COMPATIBLE_INTERFACE_BOOL "SDL3_SHARED"
                INTERFACE_SDL3_SHARED "ON"
                COMPATIBLE_INTERFACE_STRING "SDL_VERSION"
                INTERFACE_SDL_VERSION "SDL3"
        )

Is my understanding correct? And why isn't _sdl3_dll passed to INTERFACE_LINK_LIBRARIES?

This SDL3 target looks properly set up:

  • IMPORTED_IMPLIB is the .lib that is actually linked with.
  • IMPORTED_LOCATION is the .dll that is needed at runtime.
  • INTERFACE_LINK_LIBRARIES lists all the dependencies for linking, in this case, only the SDL3::Headers target. Since it is a target, "linking" to it also adds the public include directories.

What is most likely happening is that all the DLLs need to be copied to the same directory as the test executable. In CMake >=3.21 it can be done with:

add_custom_command(TARGET ${_test} POST_BUILD
  COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_RUNTIME_DLLS:${_test}> $<TARGET_FILE_DIR:${_test}>
  COMMAND_EXPAND_LISTS
 )

Otherwise, if you know about the lists of DLLs needed, you can just use:

add_custom_command(TARGET ${_test} POST_BUILD
  COMMAND ${CMAKE_COMMAND} -E copy
    $<TARGET_FILE:SDL3::SDL3>
    $<TARGET_FILE:other::dependency>
    ...
    $<TARGET_FILE_DIR:${_test}>
)

Also on the topic of CI, you may be interested in this Github Action: https://github.com/libsdl-org/setup-sdl

Remove version check
Remove version check
Fix to work with buffer
Set SDL3 standard on
Add SDL3 to unit tests
Revert
Fix SDL3 no malloc
Fix target link libraries
Fix
Fix Windows CI with SDL3 on x86 and with MinGW
Fix dependencies
Fix buffer and SDL_min
Fix CMake
Move SDL3
Fix SDL3 playback
@andyvand
Copy link
Author

andyvand commented Feb 7, 2025

It is working!
I have done a small test on the built fluidsynth binary.
It plays using the SDL3 audio driver everything beautifully.

`fluidsynth /Users/andyvand/Downloads/fluidsynth/sf2/VintageDreamsWaves-v2.sf2 /Users/andyvand/Downloads/opentyrian2000/extras/music40.mid -a sdl3
FluidSynth runtime version 2.4.3
Copyright (C) 2000-2025 Peter Hanappe and others.
Distributed under the LGPL license.
SoundFont(R) is a registered trademark of Creative Technology Ltd.

fluidsynth: warning: Sample 'SineWave': ROM sample ignored
Type 'help' for help topics.`

Update buffer
Fix SDL buffer length
Fix MinGW compile
Revert to malloc for buffer
Buffer check
@derselbst derselbst changed the base branch from master to sdl3 February 8, 2025 14:00
@derselbst
Copy link
Member

Ok, thanks so far. I'll merge this to a feature branch and will take care of the correct buffer allocation and fixing the CI build.

@derselbst derselbst merged commit 79999da into FluidSynth:sdl3 Feb 8, 2025
0 of 30 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Build fails on Windows when unicode is enabled due to incompatible entry point name with SDL2
4 participants