SDL: jack: Use ProvidesOwnCallbackThread.

https://github.com/libsdl-org/SDL/commit/86243b25894c30a595be69b4d1869261b73d1db5

From 86243b25894c30a595be69b4d1869261b73d1db5 Mon Sep 17 00:00:00 2001
From: "Ryan C. Gordon" <[EMAIL REDACTED]>
Date: Wed, 5 Jul 2023 00:43:09 -0400
Subject: [PATCH] jack: Use ProvidesOwnCallbackThread.

We were firing a semaphore from the JACK-provided thread to otherwise work
within the standard SDL2 device thread, but there's no need for this in SDL3.
---
 src/audio/jack/SDL_jackaudio.c | 118 +++++++++++++--------------------
 src/audio/jack/SDL_jackaudio.h |   3 +-
 2 files changed, 46 insertions(+), 75 deletions(-)

diff --git a/src/audio/jack/SDL_jackaudio.c b/src/audio/jack/SDL_jackaudio.c
index 36bfbb8e7385..53eb73a47409 100644
--- a/src/audio/jack/SDL_jackaudio.c
+++ b/src/audio/jack/SDL_jackaudio.c
@@ -135,9 +135,7 @@ static int load_jack_syms(void)
 
 static void jackShutdownCallback(void *arg) /* JACK went away; device is lost. */
 {
-    SDL_AudioDevice *_this = (SDL_AudioDevice *)arg;
-    SDL_AudioDeviceDisconnected(_this);
-    SDL_PostSemaphore(_this->hidden->iosem); /* unblock the SDL thread. */
+    SDL_AudioDeviceDisconnected((SDL_AudioDevice *)arg);
 }
 
 // !!! FIXME: implement and register these!
@@ -146,41 +144,29 @@ static void jackShutdownCallback(void *arg) /* JACK went away; device is lost. *
 
 static int jackProcessPlaybackCallback(jack_nframes_t nframes, void *arg)
 {
-    SDL_AudioDevice *_this = (SDL_AudioDevice *)arg;
-    jack_port_t **ports = _this->hidden->sdlports;
-    const int total_channels = _this->spec.channels;
-    const int total_frames = _this->sample_frames;
-    int channelsi;
+    SDL_assert(nframes == ((SDL_AudioDevice *)arg)->sample_frames);
+    SDL_OutputAudioThreadIterate((SDL_AudioDevice *)arg);
+    return 0;
+}
 
-    if (SDL_AtomicGet(&_this->shutdown)) {
-        /* silence the buffer to avoid repeats and corruption. */
-        SDL_memset(_this->hidden->iobuffer, _this->silence_value, _this->buffer_size);
-    }
+static void JACK_PlayDevice(SDL_AudioDevice *device, const Uint8 *ui8buffer, int buflen)
+{
+    const float *buffer = (float *) ui8buffer;
+    jack_port_t **ports = device->hidden->sdlports;
+    const int total_channels = device->spec.channels;
+    const int total_frames = device->sample_frames;
+    const jack_nframes_t nframes = (jack_nframes_t) device->sample_frames;
 
-    for (channelsi = 0; channelsi < total_channels; channelsi++) {
+    for (int channelsi = 0; channelsi < total_channels; channelsi++) {
         float *dst = (float *)JACK_jack_port_get_buffer(ports[channelsi], nframes);
         if (dst) {
-            const float *src = _this->hidden->iobuffer + channelsi;
-            int framesi;
-            for (framesi = 0; framesi < total_frames; framesi++) {
+            const float *src = buffer + channelsi;
+            for (int framesi = 0; framesi < total_frames; framesi++) {
                 *(dst++) = *src;
                 src += total_channels;
             }
         }
     }
-
-    SDL_PostSemaphore(_this->hidden->iosem); /* tell SDL thread we're done; refill the buffer. */
-    return 0;
-}
-
-/* This function waits until it is possible to write a full sound buffer */
-static void JACK_WaitDevice(SDL_AudioDevice *_this)
-{
-    if (!SDL_AtomicGet(&_this->shutdown)) {
-        if (SDL_WaitSemaphore(_this->hidden->iosem) == -1) {
-            SDL_AudioDeviceDisconnected(_this);
-        }
-    }
 }
 
 static Uint8 *JACK_GetDeviceBuf(SDL_AudioDevice *_this, int *buffer_size)
@@ -190,46 +176,36 @@ static Uint8 *JACK_GetDeviceBuf(SDL_AudioDevice *_this, int *buffer_size)
 
 static int jackProcessCaptureCallback(jack_nframes_t nframes, void *arg)
 {
-    SDL_AudioDevice *_this = (SDL_AudioDevice *)arg;
-    if (!SDL_AtomicGet(&_this->shutdown)) {
-        jack_port_t **ports = _this->hidden->sdlports;
-        const int total_channels = _this->spec.channels;
-        const int total_frames = _this->sample_frames;
-        int channelsi;
-
-        for (channelsi = 0; channelsi < total_channels; channelsi++) {
-            const float *src = (const float *)JACK_jack_port_get_buffer(ports[channelsi], nframes);
-            if (src) {
-                float *dst = _this->hidden->iobuffer + channelsi;
-                int framesi;
-                for (framesi = 0; framesi < total_frames; framesi++) {
-                    *dst = *(src++);
-                    dst += total_channels;
-                }
-            }
-        }
-    }
-
-    SDL_PostSemaphore(_this->hidden->iosem); /* tell SDL thread we're done; new buffer is ready! */
+    SDL_assert(nframes == ((SDL_AudioDevice *)arg)->sample_frames);
+    SDL_CaptureAudioThreadIterate((SDL_AudioDevice *)arg);
     return 0;
 }
 
-static int JACK_CaptureFromDevice(SDL_AudioDevice *_this, void *buffer, int buflen)
+static int JACK_CaptureFromDevice(SDL_AudioDevice *_this, void *vbuffer, int buflen)
 {
-    SDL_assert(buflen == _this->buffer_size); /* we always fill a full buffer. */
-
-    /* Wait for JACK to fill the iobuffer */
-    if (SDL_WaitSemaphore(_this->hidden->iosem) == -1) {
-        return -1;
+    float *buffer = (float *) vbuffer;
+    jack_port_t **ports = _this->hidden->sdlports;
+    const int total_channels = _this->spec.channels;
+    const int total_frames = _this->sample_frames;
+    const jack_nframes_t nframes = (jack_nframes_t) _this->sample_frames;
+
+    for (int channelsi = 0; channelsi < total_channels; channelsi++) {
+        const float *src = (const float *)JACK_jack_port_get_buffer(ports[channelsi], nframes);
+        if (src) {
+            float *dst = buffer + channelsi;
+            for (int framesi = 0; framesi < total_frames; framesi++) {
+                *dst = *(src++);
+                dst += total_channels;
+            }
+        }
     }
 
-    SDL_memcpy(buffer, _this->hidden->iobuffer, buflen);
     return buflen;
 }
 
 static void JACK_FlushCapture(SDL_AudioDevice *_this)
 {
-    SDL_WaitSemaphore(_this->hidden->iosem);
+    // do nothing, the data will just be replaced next callback.
 }
 
 static void JACK_CloseDevice(SDL_AudioDevice *_this)
@@ -250,12 +226,11 @@ static void JACK_CloseDevice(SDL_AudioDevice *_this)
             JACK_jack_client_close(_this->hidden->client);
         }
 
-        if (_this->hidden->iosem) {
-            SDL_DestroySemaphore(_this->hidden->iosem);
-        }
-
         SDL_free(_this->hidden->iobuffer);
         SDL_free(_this->hidden);
+        _this->hidden = NULL;
+
+        SDL_AudioThreadFinalize(_this);
     }
 }
 
@@ -339,16 +314,12 @@ static int JACK_OpenDevice(SDL_AudioDevice *_this)
 
     SDL_UpdatedAudioDeviceFormat(_this);
 
-    _this->hidden->iosem = SDL_CreateSemaphore(0);
-    if (!_this->hidden->iosem) {
-        SDL_free(audio_ports);
-        return -1; /* error was set by SDL_CreateSemaphore */
-    }
-
-    _this->hidden->iobuffer = (float *)SDL_calloc(1, _this->buffer_size);
-    if (!_this->hidden->iobuffer) {
-        SDL_free(audio_ports);
-        return SDL_OutOfMemory();
+    if (!_this->iscapture) {
+        _this->hidden->iobuffer = (float *)SDL_calloc(1, _this->buffer_size);
+        if (!_this->hidden->iobuffer) {
+            SDL_free(audio_ports);
+            return SDL_OutOfMemory();
+        }
     }
 
     /* Build SDL's ports, which we will connect to the device ports. */
@@ -421,8 +392,8 @@ static SDL_bool JACK_Init(SDL_AudioDriverImpl *impl)
 
     /* Set the function pointers */
     impl->OpenDevice = JACK_OpenDevice;
-    impl->WaitDevice = JACK_WaitDevice;
     impl->GetDeviceBuf = JACK_GetDeviceBuf;
+    impl->PlayDevice = JACK_PlayDevice;
     impl->CloseDevice = JACK_CloseDevice;
     impl->Deinitialize = JACK_Deinitialize;
     impl->CaptureFromDevice = JACK_CaptureFromDevice;
@@ -430,6 +401,7 @@ static SDL_bool JACK_Init(SDL_AudioDriverImpl *impl)
     impl->OnlyHasDefaultOutputDevice = SDL_TRUE;
     impl->OnlyHasDefaultCaptureDevice = SDL_TRUE;
     impl->HasCaptureSupport = SDL_TRUE;
+    impl->ProvidesOwnCallbackThread = SDL_TRUE;
 
     return SDL_TRUE; /* this audio target is available. */
 }
diff --git a/src/audio/jack/SDL_jackaudio.h b/src/audio/jack/SDL_jackaudio.h
index 91f5680d554d..a8cf81d4fa2d 100644
--- a/src/audio/jack/SDL_jackaudio.h
+++ b/src/audio/jack/SDL_jackaudio.h
@@ -28,9 +28,8 @@
 struct SDL_PrivateAudioData
 {
     jack_client_t *client;
-    SDL_Semaphore *iosem;
-    float *iobuffer;
     jack_port_t **sdlports;
+    float *iobuffer;
 };
 
 #endif /* SDL_jackaudio_h_ */