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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
diff --git a/src/audio/jack/SDL_jackaudio.c b/src/audio/jack/SDL_jackaudio.c
index a252da7..76ff431 100644
--- a/src/audio/jack/SDL_jackaudio.c
+++ b/src/audio/jack/SDL_jackaudio.c
@@ -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_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_by_name) (jack_client_t *, const char *);
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_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_buffer_size);
SDL_JACK_SYM(jack_port_register);
+ SDL_JACK_SYM(jack_port_by_name);
SDL_JACK_SYM(jack_port_name);
+ SDL_JACK_SYM(jack_port_type);
SDL_JACK_SYM(jack_connect);
SDL_JACK_SYM(jack_set_process_callback);
return 0;
@@ -273,10 +277,6 @@ JACK_CloseDevice(_THIS)
SDL_DestroySemaphore(this->hidden->iosem);
}
- if (this->hidden->devports) {
- JACK_jack_free(this->hidden->devports);
- }
-
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 char *sdlportstr = iscapture ? "input" : "output";
const char **devports = NULL;
+ int *audio_ports;
jack_client_t *client = NULL;
jack_status_t status;
int channels = 0;
+ int ports = 0;
int i;
/* 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);
- this->hidden->devports = devports;
if (!devports || !devports[0]) {
return SDL_SetError("No physical JACK ports available");
}
- while (devports[++channels]) {
+ while (devports[++ports]) {
/* 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." */
/* 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. */
for (i = 0; i < channels; i++) {
const char *sdlport = JACK_jack_port_name(this->hidden->sdlports[i]);
- const char *srcport = iscapture ? devports[i] : sdlport;
- const char *dstport = iscapture ? sdlport : devports[i];
+ const char *srcport = iscapture ? devports[audio_ports[i]] : sdlport;
+ const char *dstport = iscapture ? sdlport : devports[audio_ports[i]];
if (JACK_jack_connect(client, srcport, dstport) != 0) {
return SDL_SetError("Couldn't connect JACK ports: %s => %s", srcport, dstport);
}
}
/* don't need these anymore. */
- this->hidden->devports = NULL;
JACK_jack_free(devports);
+ SDL_free(audio_ports);
/* We're ready to rock and roll. :-) */
return 0;
diff --git a/src/audio/jack/SDL_jackaudio.h b/src/audio/jack/SDL_jackaudio.h
index aab199a..5bc04bd 100644
--- a/src/audio/jack/SDL_jackaudio.h
+++ b/src/audio/jack/SDL_jackaudio.h
@@ -33,7 +33,6 @@ struct SDL_PrivateAudioData
jack_client_t *client;
SDL_sem *iosem;
float *iobuffer;
- const char **devports;
jack_port_t **sdlports;
};