SDL_mixer: timidity: move load_sbk() stuff from song load to Timidity_Init() time

From aee60a34138d06c329f29f007c76306ee546319d Mon Sep 17 00:00:00 2001
From: Ozkan Sezer <[EMAIL REDACTED]>
Date: Sat, 15 Aug 2026 10:51:30 +0300
Subject: [PATCH] timidity: move load_sbk() stuff from song load to
 Timidity_Init() time

Timidity_SetSoundfont() now loads the specified file, therefore its
result should be checked before calling Timidity_Init(). If loading
the font fails, the font won't be set in the library.
---
 src/decoder_timidity.c  |  4 ++-
 src/timidity/sndfont.c  | 66 +++++++++++++++++++----------------------
 src/timidity/sndfont.h  |  6 +++-
 src/timidity/timidity.c | 18 ++++++++---
 src/timidity/timidity.h |  4 ++-
 5 files changed, 55 insertions(+), 43 deletions(-)

diff --git a/src/decoder_timidity.c b/src/decoder_timidity.c
index edde28e9..4abb71e0 100644
--- a/src/decoder_timidity.c
+++ b/src/decoder_timidity.c
@@ -48,7 +48,9 @@ static bool SDLCALL TIMIDITY_init(void)
 {
     const char *sf2 = SDL_getenv("TIMIDITY_SOUNDFONT");
     if (sf2) {
-        Timidity_SetSoundfont(sf2); // user override, no cfg
+        if (Timidity_SetSoundfont(sf2) < 0) { // user override, no cfg
+            return false;
+        }
     }
 
     const char *cfg = SDL_getenv("TIMIDITY_CFG");  // see if the user had one.
diff --git a/src/timidity/sndfont.c b/src/timidity/sndfont.c
index e0f1ccf0..74239392 100644
--- a/src/timidity/sndfont.c
+++ b/src/timidity/sndfont.c
@@ -27,8 +27,6 @@
  * compile flags
  *----------------------------------------------------------------*/
 
-/*#define SF_CLOSE_EACH_FILE*/
-
 /*#define SF_SUPPRESS_ENVELOPE*/
 /*#define SF_SUPPRESS_TREMOLO*/
 /*#define SF_SUPPRESS_VIBRATO*/
@@ -124,6 +122,7 @@ static void calc_filterQ(Layer *lay, SFInfo *sf, SampleList *sp);
 
 
 static SFInsts sfrec;
+static SFInfo sfinfo;
 static SFExclude *sfexclude;
 static SFOrder *sforder;
 
@@ -132,11 +131,8 @@ static const int cutoff_allowed = 0;
 #endif
 
 
-int init_soundfont(MidiSong *song, const char *fname, int order)
+int init_sbk(const char *fname)
 {
-	static SFInfo sfinfo;
-	int i;
-
 	SNDDBG(("init soundfonts `%s'\n", fname));
 
 	SDL_memset(&sfinfo, 0, sizeof(sfinfo));
@@ -145,13 +141,38 @@ int init_soundfont(MidiSong *song, const char *fname, int order)
 		SNDDBG(("can't open soundfont file %s\n", fname));
 		return -1;
 	}
+
 	sfrec.fname = SDL_strdup(fname);
-	if (!sfrec.fname) goto nomem;
+	if (!sfrec.fname) goto fail;
+
 	if (load_sbk(sfrec.io, &sfinfo) < 0) {
 		SNDDBG(("%s: bad soundfont file\n", fname));
 		goto fail;
 	}
 
+	return 0;
+
+fail:
+	end_sbk();
+	return -1;
+}
+
+void end_sbk(void)
+{
+	if (sfrec.io) {
+		SDL_CloseIO(sfrec.io);
+		sfrec.io = NULL;
+	}
+	SDL_free(sfrec.fname);
+	sfrec.fname = NULL;
+	free_sbk(&sfinfo);
+	SDL_memset(&sfinfo, 0, sizeof(sfinfo));
+}
+
+int init_soundfont(MidiSong *song, int order)
+{
+	int i;
+
 	for (i = 0; i < sfinfo.nrpresets - 1; i++) {
 		int bank = sfinfo.presethdr[i].bank;
 		int preset = sfinfo.presethdr[i].preset;
@@ -181,20 +202,9 @@ int init_soundfont(MidiSong *song, const char *fname, int order)
 	sfrec.samplepos = sfinfo.samplepos;
 	sfrec.samplesize = sfinfo.samplesize;
 
-	free_sbk(&sfinfo);
-
-#ifdef SF_CLOSE_EACH_FILE
-	SDL_CloseIO(sfrec.io);
-	sfrec.io = NULL;
-#endif
 	return 0;
 nomem:
 	song->oom = 1;
-fail:	SDL_CloseIO(sfrec.io);
-	sfrec.io = NULL;
-	SDL_free(sfrec.fname);
-	sfrec.fname = NULL;
-	free_sbk(&sfinfo);
 	return -1;
 }
 
@@ -213,13 +223,6 @@ void end_soundfont(void)
 {
 	InstList *ip, *next;
 
-	if (sfrec.io) {
-		SDL_CloseIO(sfrec.io);
-		sfrec.io = NULL;
-	}
-	SDL_free(sfrec.fname);
-	sfrec.fname = NULL;
-
 	for (ip = sfrec.instlist; ip; ip = next) {
 		next = ip->next;
 		free_sample(ip);
@@ -241,12 +244,8 @@ Instrument *load_soundfont(MidiSong *song, int order, int bank, int preset, int
 	Instrument *inst = NULL;
 
 	if (sfrec.io == NULL) {
-		if (sfrec.fname == NULL)
-			return NULL;
-		if ((sfrec.io = timi_openfile(sfrec.fname)) == NULL) {
-			SNDDBG(("can't open soundfont file %s\n", sfrec.fname));
-			return NULL;
-		}
+		SNDDBG(("NULL soundfont file pointer\n"));
+		return NULL;
 	}
 
 	for (ip = sfrec.instlist; ip; ip = ip->next) {
@@ -258,11 +257,6 @@ Instrument *load_soundfont(MidiSong *song, int order, int bank, int preset, int
 	if (ip && ip->samples)
 		inst = load_from_file(song, &sfrec, ip);
 
-#ifdef SF_CLOSE_EACH_FILE
-	SDL_CloseIO(sfrec.io);
-	sfrec.io = NULL;
-#endif
-
 	return inst;
 }
 
diff --git a/src/timidity/sndfont.h b/src/timidity/sndfont.h
index f3a1615b..8f1ca952 100644
--- a/src/timidity/sndfont.h
+++ b/src/timidity/sndfont.h
@@ -10,13 +10,17 @@
 #ifndef TIMIDITY_SNDFONT_H /* sndfont.h: soundfont loader public api */
 #define TIMIDITY_SNDFONT_H
 
+#define init_sbk          TIMI_NAMESPACE(init_sbk)
+#define end_sbk           TIMI_NAMESPACE(end_sbk)
 #define init_soundfont    TIMI_NAMESPACE(init_soundfont)
 #define end_soundfont     TIMI_NAMESPACE(end_soundfont)
 #define load_soundfont    TIMI_NAMESPACE(load_soundfont)
 #define exclude_soundfont TIMI_NAMESPACE(exclude_soundfont)
 #define order_soundfont   TIMI_NAMESPACE(order_soundfont)
 
-int init_soundfont(MidiSong *song, const char *fname, int order);
+int init_sbk(const char *fname);
+void end_sbk(void);
+int init_soundfont(MidiSong *song, int order);
 void end_soundfont(void);
 Instrument *load_soundfont(MidiSong *song, int order, int bank, int preset, int keynote);
 int exclude_soundfont(int bank, int preset, int keynote);
diff --git a/src/timidity/timidity.c b/src/timidity/timidity.c
index a29ee70e..892b5ff3 100644
--- a/src/timidity/timidity.c
+++ b/src/timidity/timidity.c
@@ -309,11 +309,11 @@ static int read_config_file(const char *name, int rcf_count)
 	SNDDBG(("%s: line %d: Ignoring multiple \"soundfont\" directives.\n", name, line));
       }
      else {
-      sf_file=SDL_strdup(w[1]);
-      if (!sf_file) goto fail;
+      if (Timidity_SetSoundfont(w[1]) < 0) goto fail;
       for (j = 2; j < words; j++) {
 	if (!(cp = SDL_strchr(w[j], '='))) {
 	  SNDDBG(("%s: line %d: bad patch option %s\n", name, line, w[j]));
+	  end_sbk();
 	  goto fail;
 	}
 	*cp++=0;
@@ -321,6 +321,7 @@ static int read_config_file(const char *name, int rcf_count)
 	  k = SDL_atoi(cp);
 	  if (k < 0 || (*cp < '0' || *cp > '9')) {
 	    SNDDBG(("%s: line %d: order must be a digit", name, line));
+	    end_sbk();
 	    goto fail;
 	  }
 	  sf_order = k;
@@ -564,10 +565,18 @@ int Timidity_Init(const char *config_file)
 
 int Timidity_SetSoundfont(const char *file)
 {
+  if (sf_file) { /* just in case ... */
+      end_sbk();
+      SDL_free(sf_file);
+      sf_file = NULL;
+  }
   if (file) {
       char *fname = SDL_strdup(file);
       if (!fname) return -1;
-      SDL_free(sf_file);
+      if (init_sbk(file) < 0) {
+          SDL_free(fname);
+          return -1;
+      }
       sf_file = fname;
   }
   return 0;
@@ -677,7 +686,7 @@ static void do_song_load(SDL_IOStream *io, const SDL_AudioSpec *audio, MidiSong
   song->default_program = DEFAULT_PROGRAM;
 
   if (sf_file) {
-    if (init_soundfont(song, sf_file, sf_order) < 0)
+    if (init_soundfont(song, sf_order) < 0)
       goto fail;
   }
 
@@ -760,6 +769,7 @@ void Timidity_Exit(void)
   }
 
   end_soundfont();
+  end_sbk();
   SDL_free(sf_file);
   sf_file = NULL;
   sf_order = 0;
diff --git a/src/timidity/timidity.h b/src/timidity/timidity.h
index 5d0145a4..1f416952 100644
--- a/src/timidity/timidity.h
+++ b/src/timidity/timidity.h
@@ -157,7 +157,9 @@ typedef struct {
 
 extern int Timidity_Init(const char *config_file);
 extern int Timidity_Init_NoConfig(void);
-/* Set the full path of a soundfont (sf2) to use. Must be called before Timidity_Init().
+/* Set the full path of a soundfont (sf2) to use, and do a preliminary load of
+ * the specified file:  MUST BE called before Timidity_Init(). If loading fails
+ * the soundfont will NOT be set.
  * If a soundfont is set, config file will not be parsed by Timidity_Init(). */
 extern int Timidity_SetSoundfont(const char *sf2_file);
 extern void Timidity_SetVolume(MidiSong *song, int volume);