SDL_mixer: Add seek, tell, and duration to fluidsynth

From 40181cb36d48f507992c6e69180aa3af6355ee14 Mon Sep 17 00:00:00 2001
From: "Stephen E. Baker" <[EMAIL REDACTED]>
Date: Thu, 11 May 2023 22:05:06 -0400
Subject: [PATCH] Add seek, tell, and duration to fluidsynth

Ensure that when playing a track it starts from the beginning.
---
 src/codecs/music_fluidsynth.c | 56 +++++++++++++++++++++++++++++++++--
 1 file changed, 54 insertions(+), 2 deletions(-)

diff --git a/src/codecs/music_fluidsynth.c b/src/codecs/music_fluidsynth.c
index 9678d2ef..141e0af5 100644
--- a/src/codecs/music_fluidsynth.c
+++ b/src/codecs/music_fluidsynth.c
@@ -39,6 +39,9 @@ typedef struct {
 #if (FLUIDSYNTH_VERSION_MAJOR >= 2)
     void (*delete_fluid_player)(fluid_player_t*);
     void (*delete_fluid_synth)(fluid_synth_t*);
+    int (*fluid_player_seek)(fluid_player_t*, int);
+    int (*fluid_player_get_total_ticks)(fluid_player_t*);
+    int (*fluid_player_get_current_tick)(fluid_player_t*);
 #else
     int (*delete_fluid_player)(fluid_player_t*);
     int (*delete_fluid_synth)(fluid_synth_t*);
@@ -85,6 +88,9 @@ static int FLUIDSYNTH_Load()
 #if (FLUIDSYNTH_VERSION_MAJOR >= 2)
         FUNCTION_LOADER(delete_fluid_player, void (*)(fluid_player_t*))
         FUNCTION_LOADER(delete_fluid_synth, void (*)(fluid_synth_t*))
+        FUNCTION_LOADER(fluid_player_seek, int (*)(fluid_player_t*, int))
+        FUNCTION_LOADER(fluid_player_get_total_ticks, int (*)(fluid_player_t*))
+        FUNCTION_LOADER(fluid_player_get_current_tick, int (*)(fluid_player_t*))
 #else
         FUNCTION_LOADER(delete_fluid_player, int (*)(fluid_player_t*))
         FUNCTION_LOADER(delete_fluid_synth, int (*)(fluid_synth_t*))
@@ -274,6 +280,16 @@ static int FLUIDSYNTH_Play(void *context, int play_count)
 {
     FLUIDSYNTH_Music *music = (FLUIDSYNTH_Music *)context;
     fluidsynth.fluid_player_set_loop(music->player, play_count);
+#if (FLUIDSYNTH_VERSION_MAJOR >= 2)
+    fluidsynth.fluid_player_seek(music->player, 0);
+#endif
+    fluidsynth.fluid_player_play(music->player);
+    return 0;
+}
+
+static int FLUIDSYNTH_Resume(void *context)
+{
+    FLUIDSYNTH_Music *music = (FLUIDSYNTH_Music*)context;
     fluidsynth.fluid_player_play(music->player);
     return 0;
 }
@@ -311,6 +327,15 @@ static int FLUIDSYNTH_GetAudio(void *context, void *data, int bytes)
 }
 
 static void FLUIDSYNTH_Stop(void *context)
+{
+    FLUIDSYNTH_Music *music = (FLUIDSYNTH_Music *)context;
+    fluidsynth.fluid_player_stop(music->player);
+#if (FLUIDSYNTH_VERSION_MAJOR >= 2)
+    fluidsynth.fluid_player_seek(music->player, 0);
+#endif
+}
+
+static void FLUIDSYNTH_Pause(void *context)
 {
     FLUIDSYNTH_Music *music = (FLUIDSYNTH_Music *)context;
     fluidsynth.fluid_player_stop(music->player);
@@ -338,6 +363,27 @@ static void FLUIDSYNTH_Delete(void *context)
     SDL_free(music);
 }
 
+#if (FLUIDSYNTH_VERSION_MAJOR >= 2)
+static int FLUIDSYNTH_Seek(void *context, double position)
+{
+    FLUIDSYNTH_Music *music = (FLUIDSYNTH_Music*)context;
+    fluidsynth.fluid_player_seek(music->player, (int)(position * 1000));
+    return 0;
+}
+
+static double FLUIDSYNTH_Tell(void *context)
+{
+    FLUIDSYNTH_Music *music = (FLUIDSYNTH_Music*)context;
+    return fluidsynth.fluid_player_get_current_tick(music->player) / 1000.0;
+}
+
+static double FLUIDSYNTH_Duration(void* context)
+{
+    FLUIDSYNTH_Music *music = (FLUIDSYNTH_Music*)context;
+    return fluidsynth.fluid_player_get_total_ticks(music->player) / 1000.0;
+}
+#endif
+
 Mix_MusicInterface Mix_MusicInterface_FLUIDSYNTH =
 {
     "FLUIDSYNTH",
@@ -356,17 +402,23 @@ Mix_MusicInterface Mix_MusicInterface_FLUIDSYNTH =
     FLUIDSYNTH_IsPlaying,
     FLUIDSYNTH_GetAudio,
     NULL,   /* Jump */
+#if (FLUIDSYNTH_VERSION_MAJOR >= 2)
+    FLUIDSYNTH_Seek,
+    FLUIDSYNTH_Tell,
+    FLUIDSYNTH_Duration,
+#else
     NULL,   /* Seek */
     NULL,   /* Tell */
     NULL,   /* Duration */
+#endif
     NULL,   /* LoopStart */
     NULL,   /* LoopEnd */
     NULL,   /* LoopLength */
     NULL,   /* GetMetaTag */
     NULL,   /* GetNumTracks */
     NULL,   /* StartTrack */
-    NULL,   /* Pause */
-    NULL,   /* Resume */
+    FLUIDSYNTH_Pause,
+    FLUIDSYNTH_Resume,
     FLUIDSYNTH_Stop,
     FLUIDSYNTH_Delete,
     NULL,   /* Close */