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.
This commit is contained in:
Ryan C. Gordon
2023-07-05 00:43:09 -04:00
parent 18906a32b8
commit 86243b2589
2 changed files with 50 additions and 79 deletions

View File

@@ -135,9 +135,7 @@ static int load_jack_syms(void)
static void jackShutdownCallback(void *arg) /* JACK went away; device is lost. */ static void jackShutdownCallback(void *arg) /* JACK went away; device is lost. */
{ {
SDL_AudioDevice *_this = (SDL_AudioDevice *)arg; SDL_AudioDeviceDisconnected((SDL_AudioDevice *)arg);
SDL_AudioDeviceDisconnected(_this);
SDL_PostSemaphore(_this->hidden->iosem); /* unblock the SDL thread. */
} }
// !!! FIXME: implement and register these! // !!! FIXME: implement and register these!
@@ -146,39 +144,27 @@ static void jackShutdownCallback(void *arg) /* JACK went away; device is lost. *
static int jackProcessPlaybackCallback(jack_nframes_t nframes, void *arg) static int jackProcessPlaybackCallback(jack_nframes_t nframes, void *arg)
{ {
SDL_AudioDevice *_this = (SDL_AudioDevice *)arg; SDL_assert(nframes == ((SDL_AudioDevice *)arg)->sample_frames);
jack_port_t **ports = _this->hidden->sdlports; SDL_OutputAudioThreadIterate((SDL_AudioDevice *)arg);
const int total_channels = _this->spec.channels;
const int total_frames = _this->sample_frames;
int channelsi;
if (SDL_AtomicGet(&_this->shutdown)) {
/* silence the buffer to avoid repeats and corruption. */
SDL_memset(_this->hidden->iobuffer, _this->silence_value, _this->buffer_size);
}
for (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++) {
*(dst++) = *src;
src += total_channels;
}
}
}
SDL_PostSemaphore(_this->hidden->iosem); /* tell SDL thread we're done; refill the buffer. */
return 0; return 0;
} }
/* This function waits until it is possible to write a full sound buffer */ static void JACK_PlayDevice(SDL_AudioDevice *device, const Uint8 *ui8buffer, int buflen)
static void JACK_WaitDevice(SDL_AudioDevice *_this)
{ {
if (!SDL_AtomicGet(&_this->shutdown)) { const float *buffer = (float *) ui8buffer;
if (SDL_WaitSemaphore(_this->hidden->iosem) == -1) { jack_port_t **ports = device->hidden->sdlports;
SDL_AudioDeviceDisconnected(_this); 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 (int channelsi = 0; channelsi < total_channels; channelsi++) {
float *dst = (float *)JACK_jack_port_get_buffer(ports[channelsi], nframes);
if (dst) {
const float *src = buffer + channelsi;
for (int framesi = 0; framesi < total_frames; framesi++) {
*(dst++) = *src;
src += total_channels;
}
} }
} }
} }
@@ -190,46 +176,36 @@ static Uint8 *JACK_GetDeviceBuf(SDL_AudioDevice *_this, int *buffer_size)
static int jackProcessCaptureCallback(jack_nframes_t nframes, void *arg) static int jackProcessCaptureCallback(jack_nframes_t nframes, void *arg)
{ {
SDL_AudioDevice *_this = (SDL_AudioDevice *)arg; SDL_assert(nframes == ((SDL_AudioDevice *)arg)->sample_frames);
if (!SDL_AtomicGet(&_this->shutdown)) { SDL_CaptureAudioThreadIterate((SDL_AudioDevice *)arg);
jack_port_t **ports = _this->hidden->sdlports; return 0;
const int total_channels = _this->spec.channels; }
const int total_frames = _this->sample_frames;
int channelsi;
for (channelsi = 0; channelsi < total_channels; channelsi++) { static int JACK_CaptureFromDevice(SDL_AudioDevice *_this, void *vbuffer, int buflen)
const float *src = (const float *)JACK_jack_port_get_buffer(ports[channelsi], nframes); {
if (src) { float *buffer = (float *) vbuffer;
float *dst = _this->hidden->iobuffer + channelsi; jack_port_t **ports = _this->hidden->sdlports;
int framesi; const int total_channels = _this->spec.channels;
for (framesi = 0; framesi < total_frames; framesi++) { const int total_frames = _this->sample_frames;
*dst = *(src++); const jack_nframes_t nframes = (jack_nframes_t) _this->sample_frames;
dst += total_channels;
} 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_PostSemaphore(_this->hidden->iosem); /* tell SDL thread we're done; new buffer is ready! */
return 0;
}
static int JACK_CaptureFromDevice(SDL_AudioDevice *_this, void *buffer, 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;
}
SDL_memcpy(buffer, _this->hidden->iobuffer, buflen);
return buflen; return buflen;
} }
static void JACK_FlushCapture(SDL_AudioDevice *_this) 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) 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); 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->iobuffer);
SDL_free(_this->hidden); SDL_free(_this->hidden);
_this->hidden = NULL;
SDL_AudioThreadFinalize(_this);
} }
} }
@@ -339,16 +314,12 @@ static int JACK_OpenDevice(SDL_AudioDevice *_this)
SDL_UpdatedAudioDeviceFormat(_this); SDL_UpdatedAudioDeviceFormat(_this);
_this->hidden->iosem = SDL_CreateSemaphore(0); if (!_this->iscapture) {
if (!_this->hidden->iosem) { _this->hidden->iobuffer = (float *)SDL_calloc(1, _this->buffer_size);
SDL_free(audio_ports); if (!_this->hidden->iobuffer) {
return -1; /* error was set by SDL_CreateSemaphore */ SDL_free(audio_ports);
} return SDL_OutOfMemory();
}
_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. */ /* 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 */ /* Set the function pointers */
impl->OpenDevice = JACK_OpenDevice; impl->OpenDevice = JACK_OpenDevice;
impl->WaitDevice = JACK_WaitDevice;
impl->GetDeviceBuf = JACK_GetDeviceBuf; impl->GetDeviceBuf = JACK_GetDeviceBuf;
impl->PlayDevice = JACK_PlayDevice;
impl->CloseDevice = JACK_CloseDevice; impl->CloseDevice = JACK_CloseDevice;
impl->Deinitialize = JACK_Deinitialize; impl->Deinitialize = JACK_Deinitialize;
impl->CaptureFromDevice = JACK_CaptureFromDevice; impl->CaptureFromDevice = JACK_CaptureFromDevice;
@@ -430,6 +401,7 @@ static SDL_bool JACK_Init(SDL_AudioDriverImpl *impl)
impl->OnlyHasDefaultOutputDevice = SDL_TRUE; impl->OnlyHasDefaultOutputDevice = SDL_TRUE;
impl->OnlyHasDefaultCaptureDevice = SDL_TRUE; impl->OnlyHasDefaultCaptureDevice = SDL_TRUE;
impl->HasCaptureSupport = SDL_TRUE; impl->HasCaptureSupport = SDL_TRUE;
impl->ProvidesOwnCallbackThread = SDL_TRUE;
return SDL_TRUE; /* this audio target is available. */ return SDL_TRUE; /* this audio target is available. */
} }

View File

@@ -28,9 +28,8 @@
struct SDL_PrivateAudioData struct SDL_PrivateAudioData
{ {
jack_client_t *client; jack_client_t *client;
SDL_Semaphore *iosem;
float *iobuffer;
jack_port_t **sdlports; jack_port_t **sdlports;
float *iobuffer;
}; };
#endif /* SDL_jackaudio_h_ */ #endif /* SDL_jackaudio_h_ */