summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorpaul <paul@0c269be4-1314-0410-8aa9-9f06e86f4224>2011-04-25 11:55:13 +0000
committerpaul <paul@0c269be4-1314-0410-8aa9-9f06e86f4224>2011-04-25 11:55:13 +0000
commit043b3924c31990d0e868958359eea7eb5b225e47 (patch)
tree6284000adf5337b95b7058cf82bab08d8e6e78d8 /drivers
parent815fabe8a8ab3fab20412bf5b005d4802441da54 (diff)
downloadjack1-043b3924c31990d0e868958359eea7eb5b225e47.tar.gz
if an ALSA device cannot be opened because its busy, try to use lsof(1) to determine which processes have the device open, and show that list to the user. Heuristic, because we don't know which /dev files map to a given ALSA device name, so test them all0.120.2
git-svn-id: svn+ssh://jackaudio.org/trunk/jack@4357 0c269be4-1314-0410-8aa9-9f06e86f4224
Diffstat (limited to 'drivers')
-rw-r--r--drivers/alsa/alsa_driver.c148
1 files changed, 137 insertions, 11 deletions
diff --git a/drivers/alsa/alsa_driver.c b/drivers/alsa/alsa_driver.c
index 6cc9cf7..f8cd209 100644
--- a/drivers/alsa/alsa_driver.c
+++ b/drivers/alsa/alsa_driver.c
@@ -1970,6 +1970,108 @@ alsa_driver_delete (alsa_driver_t *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;
+ }
+}
+
+
static jack_driver_t *
alsa_driver_new (char *name, char *playback_alsa_device,
char *capture_alsa_device,
@@ -1993,7 +2095,7 @@ alsa_driver_new (char *name, char *playback_alsa_device,
)
{
int err;
-
+ char* current_apps;
alsa_driver_t *driver;
jack_info ("creating alsa driver ... %s|%s|%" PRIu32 "|%" PRIu32
@@ -2089,11 +2191,23 @@ alsa_driver_new (char *name, char *playback_alsa_device,
SND_PCM_NONBLOCK) < 0) {
switch (errno) {
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);
+ 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;
break;
@@ -2122,11 +2236,23 @@ alsa_driver_new (char *name, char *playback_alsa_device,
SND_PCM_NONBLOCK) < 0) {
switch (errno) {
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);
return NULL;
break;