mirror of https://github.com/encounter/SDL.git
Fixed bug 4184 - jack audio driver fails in presence of midi ports
Martin ?irokov Launching an SDL application with SDL_AUDIODRIVER=jack, and then calling SDL_OpenAudioDevice() with whatever parameters fails with an error like this one: SDL_OpenAudioDevice: Couldn't connect JACK ports: SDL:sdl_jack_output_0 => system:midi_playback_1 This happens because JACK_OpenDevice in src/audio/jack/SDL_jackaudio.c blindly tries to connect to all input ports without checking whether they are for audio or midi. The fix is to check port types and ignore all non audio ports. Also I removed devports field from struct SDL_PrivateAudioData, because it's never really used and removing unused ports from it would be PITA.
This commit is contained in:
parent
03ff7dcf6b
commit
1d25135b71
|
@ -44,7 +44,9 @@ static const char ** (*JACK_jack_get_ports) (jack_client_t *, const char *, cons
|
||||||
static jack_nframes_t (*JACK_jack_get_sample_rate) (jack_client_t *);
|
static jack_nframes_t (*JACK_jack_get_sample_rate) (jack_client_t *);
|
||||||
static jack_nframes_t (*JACK_jack_get_buffer_size) (jack_client_t *);
|
static jack_nframes_t (*JACK_jack_get_buffer_size) (jack_client_t *);
|
||||||
static jack_port_t * (*JACK_jack_port_register) (jack_client_t *, const char *, const char *, unsigned long, unsigned long);
|
static jack_port_t * (*JACK_jack_port_register) (jack_client_t *, const char *, const char *, unsigned long, unsigned long);
|
||||||
|
static jack_port_t * (*JACK_jack_port_by_name) (jack_client_t *, const char *);
|
||||||
static const char * (*JACK_jack_port_name) (const jack_port_t *);
|
static const char * (*JACK_jack_port_name) (const jack_port_t *);
|
||||||
|
static const char * (*JACK_jack_port_type) (const jack_port_t *);
|
||||||
static int (*JACK_jack_connect) (jack_client_t *, const char *, const char *);
|
static int (*JACK_jack_connect) (jack_client_t *, const char *, const char *);
|
||||||
static int (*JACK_jack_set_process_callback) (jack_client_t *, JackProcessCallback, void *);
|
static int (*JACK_jack_set_process_callback) (jack_client_t *, JackProcessCallback, void *);
|
||||||
|
|
||||||
|
@ -135,7 +137,9 @@ load_jack_syms(void)
|
||||||
SDL_JACK_SYM(jack_get_sample_rate);
|
SDL_JACK_SYM(jack_get_sample_rate);
|
||||||
SDL_JACK_SYM(jack_get_buffer_size);
|
SDL_JACK_SYM(jack_get_buffer_size);
|
||||||
SDL_JACK_SYM(jack_port_register);
|
SDL_JACK_SYM(jack_port_register);
|
||||||
|
SDL_JACK_SYM(jack_port_by_name);
|
||||||
SDL_JACK_SYM(jack_port_name);
|
SDL_JACK_SYM(jack_port_name);
|
||||||
|
SDL_JACK_SYM(jack_port_type);
|
||||||
SDL_JACK_SYM(jack_connect);
|
SDL_JACK_SYM(jack_connect);
|
||||||
SDL_JACK_SYM(jack_set_process_callback);
|
SDL_JACK_SYM(jack_set_process_callback);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -273,10 +277,6 @@ JACK_CloseDevice(_THIS)
|
||||||
SDL_DestroySemaphore(this->hidden->iosem);
|
SDL_DestroySemaphore(this->hidden->iosem);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->hidden->devports) {
|
|
||||||
JACK_jack_free(this->hidden->devports);
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_free(this->hidden->iobuffer);
|
SDL_free(this->hidden->iobuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -292,9 +292,11 @@ JACK_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
||||||
const JackProcessCallback callback = iscapture ? jackProcessCaptureCallback : jackProcessPlaybackCallback;
|
const JackProcessCallback callback = iscapture ? jackProcessCaptureCallback : jackProcessPlaybackCallback;
|
||||||
const char *sdlportstr = iscapture ? "input" : "output";
|
const char *sdlportstr = iscapture ? "input" : "output";
|
||||||
const char **devports = NULL;
|
const char **devports = NULL;
|
||||||
|
int *audio_ports;
|
||||||
jack_client_t *client = NULL;
|
jack_client_t *client = NULL;
|
||||||
jack_status_t status;
|
jack_status_t status;
|
||||||
int channels = 0;
|
int channels = 0;
|
||||||
|
int ports = 0;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* Initialize all variables that we clean on shutdown */
|
/* Initialize all variables that we clean on shutdown */
|
||||||
|
@ -311,15 +313,30 @@ JACK_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
||||||
}
|
}
|
||||||
|
|
||||||
devports = JACK_jack_get_ports(client, NULL, NULL, JackPortIsPhysical | sysportflags);
|
devports = JACK_jack_get_ports(client, NULL, NULL, JackPortIsPhysical | sysportflags);
|
||||||
this->hidden->devports = devports;
|
|
||||||
if (!devports || !devports[0]) {
|
if (!devports || !devports[0]) {
|
||||||
return SDL_SetError("No physical JACK ports available");
|
return SDL_SetError("No physical JACK ports available");
|
||||||
}
|
}
|
||||||
|
|
||||||
while (devports[++channels]) {
|
while (devports[++ports]) {
|
||||||
/* spin to count devports */
|
/* spin to count devports */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Filter out non-audio ports */
|
||||||
|
audio_ports = SDL_calloc(ports, sizeof *audio_ports);
|
||||||
|
for (i = 0; i < ports; i++) {
|
||||||
|
const jack_port_t *dport = JACK_jack_port_by_name(client, devports[i]);
|
||||||
|
const char *type = JACK_jack_port_type(dport);
|
||||||
|
const int len = SDL_strlen(type);
|
||||||
|
/* See if type ends with "audio" */
|
||||||
|
if (len >= 5 && !SDL_memcmp(type+len-5, "audio", 5)) {
|
||||||
|
audio_ports[channels++] = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (channels == 0) {
|
||||||
|
return SDL_SetError("No physical JACK ports available");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* !!! FIXME: docs say about buffer size: "This size may change, clients that depend on it must register a bufsize_callback so they will be notified if it does." */
|
/* !!! FIXME: docs say about buffer size: "This size may change, clients that depend on it must register a bufsize_callback so they will be notified if it does." */
|
||||||
|
|
||||||
/* Jack pretty much demands what it wants. */
|
/* Jack pretty much demands what it wants. */
|
||||||
|
@ -368,16 +385,16 @@ JACK_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
||||||
/* once activated, we can connect all the ports. */
|
/* once activated, we can connect all the ports. */
|
||||||
for (i = 0; i < channels; i++) {
|
for (i = 0; i < channels; i++) {
|
||||||
const char *sdlport = JACK_jack_port_name(this->hidden->sdlports[i]);
|
const char *sdlport = JACK_jack_port_name(this->hidden->sdlports[i]);
|
||||||
const char *srcport = iscapture ? devports[i] : sdlport;
|
const char *srcport = iscapture ? devports[audio_ports[i]] : sdlport;
|
||||||
const char *dstport = iscapture ? sdlport : devports[i];
|
const char *dstport = iscapture ? sdlport : devports[audio_ports[i]];
|
||||||
if (JACK_jack_connect(client, srcport, dstport) != 0) {
|
if (JACK_jack_connect(client, srcport, dstport) != 0) {
|
||||||
return SDL_SetError("Couldn't connect JACK ports: %s => %s", srcport, dstport);
|
return SDL_SetError("Couldn't connect JACK ports: %s => %s", srcport, dstport);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* don't need these anymore. */
|
/* don't need these anymore. */
|
||||||
this->hidden->devports = NULL;
|
|
||||||
JACK_jack_free(devports);
|
JACK_jack_free(devports);
|
||||||
|
SDL_free(audio_ports);
|
||||||
|
|
||||||
/* We're ready to rock and roll. :-) */
|
/* We're ready to rock and roll. :-) */
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -33,7 +33,6 @@ struct SDL_PrivateAudioData
|
||||||
jack_client_t *client;
|
jack_client_t *client;
|
||||||
SDL_sem *iosem;
|
SDL_sem *iosem;
|
||||||
float *iobuffer;
|
float *iobuffer;
|
||||||
const char **devports;
|
|
||||||
jack_port_t **sdlports;
|
jack_port_t **sdlports;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue