|
@@ -1825,6 +1825,107 @@ alsa_driver_delete (alsa_driver_t *driver) |
|
|
free (driver); |
|
|
free (driver); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static char* |
|
|
|
|
|
discover_alsa_using_apps () |
|
|
|
|
|
{ |
|
|
|
|
|
char found[2048]; |
|
|
|
|
|
char command[5192]; |
|
|
|
|
|
char* path = getenv ("PATH"); |
|
|
|
|
|
char* dir; |
|
|
|
|
|
size_t flen = 0; |
|
|
|
|
|
int card; |
|
|
|
|
|
int device; |
|
|
|
|
|
size_t cmdlen = 0; |
|
|
|
|
|
|
|
|
|
|
|
if (!path) { |
|
|
|
|
|
return NULL; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* look for lsof and give up if its not in PATH */ |
|
|
|
|
|
|
|
|
|
|
|
path = strdup (path); |
|
|
|
|
|
dir = strtok (path, ":"); |
|
|
|
|
|
while (dir) { |
|
|
|
|
|
char maybe[PATH_MAX+1]; |
|
|
|
|
|
snprintf (maybe, sizeof(maybe), "%s/lsof", dir); |
|
|
|
|
|
if (access (maybe, X_OK)) { |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
dir = strtok (NULL, ":"); |
|
|
|
|
|
} |
|
|
|
|
|
free (path); |
|
|
|
|
|
|
|
|
|
|
|
if (!dir) { |
|
|
|
|
|
return NULL; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
snprintf (command, sizeof (command), "lsof -Fc0 "); |
|
|
|
|
|
cmdlen = strlen (command); |
|
|
|
|
|
|
|
|
|
|
|
for (card = 0; card < 8; ++card) { |
|
|
|
|
|
for (device = 0; device < 8; ++device) { |
|
|
|
|
|
char buf[32]; |
|
|
|
|
|
|
|
|
|
|
|
snprintf (buf, sizeof (buf), "/dev/snd/pcmC%dD%dp", card, device); |
|
|
|
|
|
if (access (buf, F_OK) == 0) { |
|
|
|
|
|
snprintf (command+cmdlen, sizeof(command)-cmdlen, "%s ", buf); |
|
|
|
|
|
} |
|
|
|
|
|
cmdlen = strlen (command); |
|
|
|
|
|
|
|
|
|
|
|
snprintf (buf, sizeof (buf), "/dev/snd/pcmC%dD%dc", card, device); |
|
|
|
|
|
if (access (buf, F_OK) == 0) { |
|
|
|
|
|
snprintf (command+cmdlen, sizeof(command)-cmdlen, "%s ", buf); |
|
|
|
|
|
} |
|
|
|
|
|
cmdlen = strlen (command); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
FILE* f = popen (command, "r"); |
|
|
|
|
|
|
|
|
|
|
|
if (!f) { |
|
|
|
|
|
return NULL; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
while (!feof (f)) { |
|
|
|
|
|
char buf[1024]; /* lsof doesn't output much */ |
|
|
|
|
|
|
|
|
|
|
|
if (!fgets (buf, sizeof (buf), f)) { |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (*buf != 'p') { |
|
|
|
|
|
return NULL; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* buf contains NULL as a separator between the process field and the command field */ |
|
|
|
|
|
char *pid = buf; |
|
|
|
|
|
++pid; /* skip leading 'p' */ |
|
|
|
|
|
char *cmd = pid; |
|
|
|
|
|
|
|
|
|
|
|
/* skip to NULL */ |
|
|
|
|
|
while (*cmd) { |
|
|
|
|
|
++cmd; |
|
|
|
|
|
} |
|
|
|
|
|
++cmd; /* skip to 'c' */ |
|
|
|
|
|
++cmd; /* skip to first character of command */ |
|
|
|
|
|
|
|
|
|
|
|
snprintf (found+flen, sizeof (found)-flen, "%s (process ID %s)\n", cmd, pid); |
|
|
|
|
|
flen = strlen (found); |
|
|
|
|
|
|
|
|
|
|
|
if (flen >= sizeof (found)) { |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
pclose (f); |
|
|
|
|
|
|
|
|
|
|
|
if (flen) { |
|
|
|
|
|
return strdup (found); |
|
|
|
|
|
} else { |
|
|
|
|
|
return NULL; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
jack_driver_t * |
|
|
jack_driver_t * |
|
|
alsa_driver_new (char *name, char *playback_alsa_device, |
|
|
alsa_driver_new (char *name, char *playback_alsa_device, |
|
|
char *capture_alsa_device, |
|
|
char *capture_alsa_device, |
|
@@ -1848,7 +1949,7 @@ alsa_driver_new (char *name, char *playback_alsa_device, |
|
|
) |
|
|
) |
|
|
{ |
|
|
{ |
|
|
int err; |
|
|
int err; |
|
|
|
|
|
|
|
|
|
|
|
char* current_apps; |
|
|
alsa_driver_t *driver; |
|
|
alsa_driver_t *driver; |
|
|
|
|
|
|
|
|
jack_info ("creating alsa driver ... %s|%s|%" PRIu32 "|%" PRIu32 |
|
|
jack_info ("creating alsa driver ... %s|%s|%" PRIu32 "|%" PRIu32 |
|
@@ -1946,14 +2047,25 @@ alsa_driver_new (char *name, char *playback_alsa_device, |
|
|
SND_PCM_NONBLOCK) < 0) { |
|
|
SND_PCM_NONBLOCK) < 0) { |
|
|
switch (errno) { |
|
|
switch (errno) { |
|
|
case EBUSY: |
|
|
case EBUSY: |
|
|
jack_error ("the playback device \"%s\" is " |
|
|
|
|
|
"already in use. Please stop the" |
|
|
|
|
|
" application using it and " |
|
|
|
|
|
"run JACK again", |
|
|
|
|
|
playback_alsa_device); |
|
|
|
|
|
alsa_driver_delete (driver); |
|
|
|
|
|
|
|
|
current_apps = discover_alsa_using_apps (); |
|
|
|
|
|
if (current_apps) { |
|
|
|
|
|
jack_error ("\n\nATTENTION: The playback device \"%s\" is " |
|
|
|
|
|
"already in use. The following applications " |
|
|
|
|
|
" are using your soundcard(s) so you should " |
|
|
|
|
|
" check them and stop them as necessary before " |
|
|
|
|
|
" trying to start JACK again:\n\n%s", |
|
|
|
|
|
playback_alsa_device, |
|
|
|
|
|
current_apps); |
|
|
|
|
|
free (current_apps); |
|
|
|
|
|
} else { |
|
|
|
|
|
jack_error ("\n\nATTENTION: The playback device \"%s\" is " |
|
|
|
|
|
"already in use. Please stop the" |
|
|
|
|
|
" application using it and " |
|
|
|
|
|
"run JACK again", |
|
|
|
|
|
playback_alsa_device); |
|
|
|
|
|
} |
|
|
|
|
|
alsa_driver_delete (driver); |
|
|
return NULL; |
|
|
return NULL; |
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
case EPERM: |
|
|
case EPERM: |
|
|
jack_error ("you do not have permission to open " |
|
|
jack_error ("you do not have permission to open " |
|
@@ -1979,11 +2091,23 @@ alsa_driver_new (char *name, char *playback_alsa_device, |
|
|
SND_PCM_NONBLOCK) < 0) { |
|
|
SND_PCM_NONBLOCK) < 0) { |
|
|
switch (errno) { |
|
|
switch (errno) { |
|
|
case EBUSY: |
|
|
case EBUSY: |
|
|
jack_error ("the capture device \"%s\" is " |
|
|
|
|
|
"already in use. Please stop the" |
|
|
|
|
|
" application using it and " |
|
|
|
|
|
"run JACK again", |
|
|
|
|
|
capture_alsa_device); |
|
|
|
|
|
|
|
|
current_apps = discover_alsa_using_apps (); |
|
|
|
|
|
if (current_apps) { |
|
|
|
|
|
jack_error ("\n\nATTENTION: The capture device \"%s\" is " |
|
|
|
|
|
"already in use. The following applications " |
|
|
|
|
|
" are using your soundcard(s) so you should " |
|
|
|
|
|
" check them and stop them as necessary before " |
|
|
|
|
|
" trying to start JACK again:\n\n%s", |
|
|
|
|
|
capture_alsa_device, |
|
|
|
|
|
current_apps); |
|
|
|
|
|
free (current_apps); |
|
|
|
|
|
} else { |
|
|
|
|
|
jack_error ("\n\nATTENTION: The capture (recording) device \"%s\" is " |
|
|
|
|
|
"already in use. Please stop the" |
|
|
|
|
|
" application using it and " |
|
|
|
|
|
"run JACK again", |
|
|
|
|
|
capture_alsa_device); |
|
|
|
|
|
} |
|
|
alsa_driver_delete (driver); |
|
|
alsa_driver_delete (driver); |
|
|
return NULL; |
|
|
return NULL; |
|
|
break; |
|
|
break; |
|
|